· 6 years ago · Sep 07, 2019, 05:36 PM
1{
2 "D:bin",
3 "{\
4 \"F:bg\",\
5 \"\\\"\\\\\\\
6if not shell.launchProcess then\\\\\\\
7 printError( \\\\\\\"Requires multishell\\\\\\\" )\\\\\\\
8 return\\\\\\\
9end\\\\\\\
10\\\\\\\
11local tArgs = { ... }\\\\\\\
12if #tArgs > 0 then\\\\\\\
13 shell.launchProcess( table.unpack( tArgs ) )\\\\\\\
14else\\\\\\\
15 shell.launchProcess( \\\\\\\"shell\\\\\\\" )\\\\\\\
16end\\\"\",\
17 \"F:cat\",\
18 \"\\\"local tArgs = {...}\\\\\\\
19\\\\\\\
20if #tArgs >= 1 then\\\\\\\
21 path = shell.resolve(tArgs[1])\\\\\\\
22 if fs.isReadOnly(path) then\\\\\\\
23 --return\\\\\\\
24 end\\\\\\\
25 if not fs.exists(path) or fs.isDir(path) then\\\\\\\
26 print(\\\\\\\"File does not exist\\\\\\\")\\\\\\\
27 else\\\\\\\
28 textutils.pagedPrint(kreadfile(path))\\\\\\\
29 end\\\\\\\
30else\\\\\\\
31 print(\\\\\\\"Filename not specified\\\\\\\")\\\\\\\
32end\\\\\\\
33\\\"\",\
34 \"F:df\",\
35 \"\\\"local sz = fs.getSize(shell.dir())\\\\\\\
36local fspc = fs.getFreeSpace(shell.dir())\\\\\\\
37print(\\\\\\\"Type: \\\\\\\"..fs.getDrive(shell.dir()))\\\\\\\
38print(\\\\\\\"Size: \\\\\\\", tostring(sz)..\\\\\\\" B\\\\\\\")\\\\\\\
39print(\\\\\\\"Free space: \\\\\\\", tostring(fspc)..\\\\\\\" B\\\\\\\")\\\"\",\
40 \"F:dism\",\
41 \"\\\"local tArgs = {...}\\\\\\\
42\\\\\\\
43local FFormat = \\\\\\\".odi\\\\\\\"\\\\\\\
44local nFile, nDir, size = 0, 0\\\\\\\
45\\\\\\\
46local function getPath(input)\\\\\\\
47 if string.sub(input, 1, 1)==\\\\\\\"/\\\\\\\" then\\\\\\\
48 path = input\\\\\\\
49 else\\\\\\\
50 path=(\\\\\\\"/\\\\\\\" .. shell.dir() .. \\\\\\\"/\\\\\\\" .. input)\\\\\\\
51 end\\\\\\\
52 return path\\\\\\\
53end\\\\\\\
54\\\\\\\
55local function fopen(path, mode)\\\\\\\
56 local f = fs.open(path, mode)\\\\\\\
57 if not f then \\\\\\\
58 stderr(\\\\\\\"ERROR: Could not open \\\\\\\"..path..\\\\\\\" with mode \\\\\\\\\\\\\\\"\\\\\\\"..mode..\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\")\\\\\\\
59 exit()\\\\\\\
60 end\\\\\\\
61 return f\\\\\\\
62end\\\\\\\
63\\\\\\\
64local function skip(df)\\\\\\\
65 local skip = {\\\\\\\"rom\\\\\\\", \\\\\\\"treasure\\\\\\\", \\\\\\\"tmp\\\\\\\"}\\\\\\\
66 for _,v in ipairs(skip) do\\\\\\\
67 if fs.getName(df) == v then\\\\\\\
68\\\\009 return true\\\\\\\
69\\\\009end\\\\\\\
70 end\\\\\\\
71 return false\\\\\\\
72end\\\\\\\
73\\\\\\\
74local function zip(file)\\\\\\\
75 print(\\\\\\\"[DISM] Capturing from FS: \\\\\\\".. file)\\\\\\\
76 local f = fopen(file, \\\\\\\"r\\\\\\\")\\\\\\\
77 local z = textutils.serialize(f.readAll())\\\\\\\
78 f.close()\\\\\\\
79 return z\\\\\\\
80end\\\\\\\
81\\\\\\\
82local function capture(path)\\\\\\\
83 local list = fs.list(path)\\\\\\\
84 local array = {}\\\\\\\
85 local t, name, d = 0, \\\\\\\"\\\\\\\", 0\\\\\\\
86 \\\\\\\
87 for i = 2, #list * 2, 2 do\\\\\\\
88 t = i/2\\\\\\\
89 local tpath = path..\\\\\\\"/\\\\\\\"..list[t]\\\\\\\
90 if fs.isDir(tpath) then\\\\\\\
91 if not skip(tpath) then\\\\\\\
92 name = \\\\\\\"D:\\\\\\\"..list[t]\\\\\\\
93 array[i] = capture(tpath)\\\\\\\
94 nDir = nDir + 1\\\\\\\
95 end\\\\\\\
96 else\\\\\\\
97 name = \\\\\\\"F:\\\\\\\"..list[t]\\\\\\\
98 array[i] = zip(tpath)\\\\\\\
99 nFile = nFile + 1\\\\\\\
100 end\\\\\\\
101 array[i - 1] = name\\\\\\\
102 end\\\\\\\
103 \\\\\\\
104 return textutils.serialize(array)\\\\\\\
105end\\\\\\\
106\\\\\\\
107local function unzip(text, path)\\\\\\\
108 print(\\\\\\\"[DISM] Applying to FS: \\\\\\\"..path)\\\\\\\
109 local f = fopen(path, \\\\\\\"w\\\\\\\")\\\\\\\
110 f.write(textutils.unserialize(text))\\\\\\\
111 f.close()\\\\\\\
112end\\\\\\\
113\\\\\\\
114local function apply(text, path)\\\\\\\
115 local array = textutils.unserialize(text)\\\\\\\
116 local unz, dp\\\\\\\
117 local d = 0\\\\\\\
118 for i = 2, #array, 2 do\\\\\\\
119 if string.sub(array[i-1], 1, 1) == \\\\\\\"D\\\\\\\" then\\\\\\\
120 dp = string.sub(array[i-1], 3, #array[i-1])\\\\\\\
121 fs.makeDir(path..\\\\\\\"/\\\\\\\"..dp)\\\\\\\
122 apply(array[i], path..\\\\\\\"/\\\\\\\"..dp)\\\\\\\
123 nDir = nDir + 1\\\\\\\
124 elseif string.sub(array[i-1], 1, 1) == \\\\\\\"F\\\\\\\" then\\\\\\\
125 local p = string.sub(array[i-1], 3, #array[i-1])\\\\\\\
126 unzip(array[i], path..\\\\\\\"/\\\\\\\"..p)\\\\\\\
127 nFile = nFile + 1\\\\\\\
128 end\\\\\\\
129 end\\\\\\\
130end\\\\\\\
131\\\\\\\
132local function result()\\\\\\\
133 print(\\\\\\\"Operation completed.\\\\\\\"\\\\\\\
134 ..\\\\\\\"\\\\\\\\n size: \\\\\\\"\\\\\\\
135 ..tostring(size).. \\\\\\\" B \\\\\\\"\\\\\\\
136 ..tostring(math.floor(size/1024)).. \\\\\\\" KB\\\\\\\"\\\\\\\
137 ..\\\\\\\"\\\\\\\\n Files: \\\\\\\".. tostring(nFile)\\\\\\\
138 ..\\\\\\\"\\\\\\\\n Folders: \\\\\\\".. tostring(nDir)\\\\\\\
139 )\\\\\\\
140end\\\\\\\
141\\\\\\\
142local outStr = \\\\\\\"Deployment Image Servicing and Management \\\\\\\\n\\\\\\\\n\\\\\\\"\\\\\\\
143\\\\\\\
144if tArgs[2] then\\\\\\\
145 tArgs[2]=getPath(tArgs[2])\\\\\\\
146end\\\\\\\
147\\\\\\\
148if #tArgs < 3 then \\\\\\\
149 outStr = outStr..[[\\\\\\\
150Usage:\\\\\\\
151dism capture <source directory> <output image>\\\\\\\
152 OR\\\\\\\
153 apply <source image> <target directory>\\\\\\\
154 \\\\\\\
155 Original code by 1Ridav.\\\\\\\
156 Modified for Orbital by minebuild02.\\\\\\\
157]]\\\\\\\
158end\\\\\\\
159\\\\\\\
160print(outStr)\\\\\\\
161\\\\\\\
162if tArgs[1] == \\\\\\\"capture\\\\\\\" then\\\\\\\
163 if fs.exists(tArgs[2]) and fs.isDir(tArgs[2]) then\\\\\\\
164 local zipped = capture(shell.resolve(tArgs[2]))\\\\\\\
165 local f = fs.open(tArgs[3]..FFormat, \\\\\\\"w\\\\\\\")\\\\\\\
166 f.write(zipped)\\\\\\\
167 f.close()\\\\\\\
168 zipped = nil\\\\\\\
169 size = fs.getSize(tArgs[3]..FFormat)\\\\\\\
170 result() \\\\\\\
171 end\\\\\\\
172 \\\\\\\
173elseif tArgs[1] == \\\\\\\"apply\\\\\\\" then\\\\\\\
174 local f = fopen(tArgs[2], \\\\\\\"r\\\\\\\")\\\\\\\
175 if not fs.exists(tArgs[3]) then \\\\\\\
176 fs.makeDir(tArgs[3]) \\\\\\\
177 end\\\\\\\
178 apply(f.readAll(), tArgs[3])\\\\\\\
179 size = fs.getSize(tArgs[2])\\\\\\\
180 result()\\\\\\\
181end\\\"\",\
182 \"F:fg\",\
183 \"\\\"\\\\\\\
184if not shell.launchProcess then\\\\\\\
185 printError( \\\\\\\"Requires multishell\\\\\\\" )\\\\\\\
186 return\\\\\\\
187end\\\\\\\
188\\\\\\\
189local tArgs = { ... }\\\\\\\
190if #tArgs > 0 then\\\\\\\
191 local nTask = shell.launchProcess( table.unpack( tArgs ) )\\\\\\\
192 if nTask then\\\\\\\
193 shell.setProcessFocus( nTask )\\\\\\\
194 end\\\\\\\
195else\\\\\\\
196 local nTask = shell.launchProcess( \\\\\\\"shell\\\\\\\" )\\\\\\\
197 if nTask then\\\\\\\
198 shell.setProcessFocus( nTask )\\\\\\\
199 end\\\\\\\
200end\\\"\",\
201 \"F:lc\",\
202 \"\\\"-- Lua compiler for the Orbital SDK\\\\\\\
203-- Takes the input file and converts it to Lua bytecode\\\\\\\
204\\\\\\\
205local oex_template = \\\\\\\"!LC!\\\\\\\\\\\\\\\\|/%s\\\\\\\\\\\\\\\\|/%s\\\\\\\"\\\\\\\
206\\\\\\\
207local function compileString(s)\\\\\\\
208 local func, err = loadstring(s)\\\\\\\
209 if func ~= nil then\\\\\\\
210 return string.dump(func)\\\\\\\
211 else\\\\\\\
212 return nil\\\\\\\
213 end\\\\\\\
214end\\\\\\\
215\\\\\\\
216local function compileFile(p)\\\\\\\
217 local func, err = loadstring(kreadfile(p))\\\\\\\
218 if func ~= nil then\\\\\\\
219 local h = fs.open(p..\\\\\\\".bin\\\\\\\", fs.AF_WRITE)\\\\\\\
220 h.write(string.dump(func))\\\\\\\
221 h.close()\\\\\\\
222 return true\\\\\\\
223 else\\\\\\\
224 return false\\\\\\\
225 end\\\\\\\
226end\\\\\\\
227\\\\\\\
228local tArgs = {...}\\\\\\\
229\\\\\\\
230if #tArgs >= 1 then\\\\\\\
231 path = shell.resolve(tArgs[1])\\\\\\\
232 if not fs.exists(path) or fs.isDir(path) then\\\\\\\
233 UI.outputInfo(\\\\\\\"lc\\\\\\\", \\\\\\\"file does not exist\\\\\\\")\\\\\\\
234 else\\\\\\\
235 UI.outputInfo(\\\\\\\"lc\\\\\\\", \\\\\\\"compiling to bytecode\\\\\\\")\\\\\\\
236 compileFile(path)\\\\\\\
237 end\\\\\\\
238else\\\\\\\
239 UI.outputInfo(\\\\\\\"lc\\\\\\\", \\\\\\\"lc <input file> [format]\\\\\\\")\\\\\\\
240end\\\\\\\
241\\\"\",\
242 \"F:msh\",\
243 \"\\\"\\\\\\\
244local process = process\\\\\\\
245local parentShell = shell\\\\\\\
246local parentTerm = term.current()\\\\\\\
247\\\\\\\
248if process then\\\\\\\
249 process.setTitle( process.getCurrent(), \\\\\\\"shell\\\\\\\" )\\\\\\\
250end\\\\\\\
251\\\\\\\
252local bExit = false\\\\\\\
253local sDir = (parentShell and parentShell.dir()) or \\\\\\\"\\\\\\\"\\\\\\\
254local sPath = (parentShell and parentShell.path()) or \\\\\\\".:/rom/programs\\\\\\\"\\\\\\\
255local tAliases = (parentShell and parentShell.aliases()) or {}\\\\\\\
256local tCompletionInfo = (parentShell and parentShell.getCompletionInfo()) or {}\\\\\\\
257local tProgramStack = {}\\\\\\\
258\\\\\\\
259local shell = {}\\\\\\\
260local function createShellEnv( sDir )\\\\\\\
261 local tEnv = {}\\\\\\\
262 tEnv[ \\\\\\\"shell\\\\\\\" ] = shell\\\\\\\
263 tEnv[ \\\\\\\"process\\\\\\\" ] = process\\\\\\\
264\\\\\\\
265 local package = {}\\\\\\\
266 package.loaded = {\\\\\\\
267 _G = _G,\\\\\\\
268 bit32 = bit32,\\\\\\\
269 coroutine = coroutine,\\\\\\\
270 math = math,\\\\\\\
271 package = package,\\\\\\\
272 string = string,\\\\\\\
273 table = table,\\\\\\\
274 }\\\\\\\
275 package.path = \\\\\\\"?;?.lua;?/init.lua;/rom/modules/main/?;/rom/modules/main/?.lua;/rom/modules/main/?/init.lua\\\\\\\"\\\\\\\
276 if turtle then\\\\\\\
277 package.path = package.path..\\\\\\\";/rom/modules/turtle/?;/rom/modules/turtle/?.lua;/rom/modules/turtle/?/init.lua\\\\\\\"\\\\\\\
278 elseif command then\\\\\\\
279 package.path = package.path..\\\\\\\";/rom/modules/command/?;/rom/modules/command/?.lua;/rom/modules/command/?/init.lua\\\\\\\"\\\\\\\
280 end\\\\\\\
281 package.config = \\\\\\\"/\\\\\\\\n;\\\\\\\\n?\\\\\\\\n!\\\\\\\\n-\\\\\\\"\\\\\\\
282 package.preload = {}\\\\\\\
283 package.loaders = {\\\\\\\
284 function( name )\\\\\\\
285 if package.preload[name] then\\\\\\\
286 return package.preload[name]\\\\\\\
287 else\\\\\\\
288 return nil, \\\\\\\"no field package.preload['\\\\\\\" .. name .. \\\\\\\"']\\\\\\\"\\\\\\\
289 end\\\\\\\
290 end,\\\\\\\
291 function( name )\\\\\\\
292 local fname = string.gsub(name, \\\\\\\"%.\\\\\\\", \\\\\\\"/\\\\\\\")\\\\\\\
293 local sError = \\\\\\\"\\\\\\\"\\\\\\\
294 for pattern in string.gmatch(package.path, \\\\\\\"[^;]+\\\\\\\") do\\\\\\\
295 local sPath = string.gsub(pattern, \\\\\\\"%?\\\\\\\", fname)\\\\\\\
296 if sPath:sub(1,1) ~= \\\\\\\"/\\\\\\\" then\\\\\\\
297 sPath = fs.combine(sDir, sPath)\\\\\\\
298 end\\\\\\\
299 if fs.exists(sPath) and not fs.isDir(sPath) then\\\\\\\
300 local fnFile, sError = loadfile( sPath, tEnv )\\\\\\\
301 if fnFile then\\\\\\\
302 return fnFile, sPath\\\\\\\
303 else\\\\\\\
304 return nil, sError\\\\\\\
305 end\\\\\\\
306 else\\\\\\\
307 if #sError > 0 then\\\\\\\
308 sError = sError .. \\\\\\\"\\\\\\\\n\\\\\\\"\\\\\\\
309 end\\\\\\\
310 sError = sError .. \\\\\\\"no file '\\\\\\\" .. sPath .. \\\\\\\"'\\\\\\\"\\\\\\\
311 end\\\\\\\
312 end\\\\\\\
313 return nil, sError\\\\\\\
314 end\\\\\\\
315 }\\\\\\\
316\\\\\\\
317 local sentinel = {}\\\\\\\
318 local function require( name )\\\\\\\
319 if type( name ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
320 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( name ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
321 end\\\\\\\
322 if package.loaded[name] == sentinel then\\\\\\\
323 error(\\\\\\\"Loop detected requiring '\\\\\\\" .. name .. \\\\\\\"'\\\\\\\", 0)\\\\\\\
324 end\\\\\\\
325 if package.loaded[name] then\\\\\\\
326 return package.loaded[name]\\\\\\\
327 end\\\\\\\
328\\\\\\\
329 local sError = \\\\\\\"Error loading module '\\\\\\\" .. name .. \\\\\\\"':\\\\\\\"\\\\\\\
330 for n,searcher in ipairs(package.loaders) do\\\\\\\
331 local loader, err = searcher(name)\\\\\\\
332 if loader then\\\\\\\
333 package.loaded[name] = sentinel\\\\\\\
334 local result = loader( err )\\\\\\\
335 if result ~= nil then\\\\\\\
336 package.loaded[name] = result\\\\\\\
337 return result\\\\\\\
338 else\\\\\\\
339 package.loaded[name] = true\\\\\\\
340 return true\\\\\\\
341 end\\\\\\\
342 else\\\\\\\
343 sError = sError .. \\\\\\\"\\\\\\\\n\\\\\\\" .. err\\\\\\\
344 end\\\\\\\
345 end\\\\\\\
346 error(sError, 2)\\\\\\\
347 end\\\\\\\
348\\\\\\\
349 tEnv[\\\\\\\"package\\\\\\\"] = package\\\\\\\
350 tEnv[\\\\\\\"require\\\\\\\"] = require\\\\\\\
351\\\\\\\
352 return tEnv\\\\\\\
353end\\\\\\\
354\\\\\\\
355-- Colours\\\\\\\
356local promptColour, textColour, bgColour\\\\\\\
357if term.isColour() then\\\\\\\
358 promptColour = colours.yellow\\\\\\\
359 textColour = colours.white\\\\\\\
360 bgColour = colours.black\\\\\\\
361else\\\\\\\
362 promptColour = colours.white\\\\\\\
363 textColour = colours.white\\\\\\\
364 bgColour = colours.black\\\\\\\
365end\\\\\\\
366\\\\\\\
367local function run( _sCommand, ... )\\\\\\\
368 local sPath = shell.resolveProgram( _sCommand )\\\\\\\
369 if sPath ~= nil then\\\\\\\
370 tProgramStack[#tProgramStack + 1] = sPath\\\\\\\
371 if process then\\\\\\\
372 local sTitle = fs.getName( sPath )\\\\\\\
373 if sTitle:sub(-4) == \\\\\\\".lua\\\\\\\" then\\\\\\\
374 sTitle = sTitle:sub(1,-5)\\\\\\\
375 end\\\\\\\
376 process.setTitle( process.getCurrent(), sTitle )\\\\\\\
377 end\\\\\\\
378 local sDir = fs.getDir( sPath )\\\\\\\
379 local result = os.run( createShellEnv( sDir ), sPath, ... )\\\\\\\
380 tProgramStack[#tProgramStack] = nil\\\\\\\
381 if process then\\\\\\\
382 if #tProgramStack > 0 then\\\\\\\
383 local sTitle = fs.getName( tProgramStack[#tProgramStack] )\\\\\\\
384 if sTitle:sub(-4) == \\\\\\\".lua\\\\\\\" then\\\\\\\
385 sTitle = sTitle:sub(1,-5)\\\\\\\
386 end\\\\\\\
387 process.setTitle( process.getCurrent(), sTitle )\\\\\\\
388 else\\\\\\\
389 process.setTitle( process.getCurrent(), \\\\\\\"shell\\\\\\\" )\\\\\\\
390 end\\\\\\\
391 end\\\\\\\
392 return result\\\\\\\
393 else\\\\\\\
394 printError( \\\\\\\"No such program\\\\\\\" )\\\\\\\
395 return false\\\\\\\
396 end\\\\\\\
397end\\\\\\\
398\\\\\\\
399local function tokenise( ... )\\\\\\\
400 local sLine = table.concat( { ... }, \\\\\\\" \\\\\\\" )\\\\\\\
401 local tWords = {}\\\\\\\
402 local bQuoted = false\\\\\\\
403 for match in string.gmatch( sLine .. \\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\", \\\\\\\"(.-)\\\\\\\\\\\\\\\"\\\\\\\" ) do\\\\\\\
404 if bQuoted then\\\\\\\
405 table.insert( tWords, match )\\\\\\\
406 else\\\\\\\
407 for m in string.gmatch( match, \\\\\\\"[^ \\\\\\\\t]+\\\\\\\" ) do\\\\\\\
408 table.insert( tWords, m )\\\\\\\
409 end\\\\\\\
410 end\\\\\\\
411 bQuoted = not bQuoted\\\\\\\
412 end\\\\\\\
413 return tWords\\\\\\\
414end\\\\\\\
415\\\\\\\
416-- Install shell API\\\\\\\
417function shell.run( ... )\\\\\\\
418 local tWords = tokenise( ... )\\\\\\\
419 local sCommand = tWords[1]\\\\\\\
420 if sCommand then\\\\\\\
421 return run( sCommand, table.unpack( tWords, 2 ) )\\\\\\\
422 end\\\\\\\
423 return false\\\\\\\
424end\\\\\\\
425\\\\\\\
426function shell.exit()\\\\\\\
427 bExit = true\\\\\\\
428end\\\\\\\
429\\\\\\\
430function shell.dir()\\\\\\\
431 return sDir\\\\\\\
432end\\\\\\\
433\\\\\\\
434function shell.setDir( _sDir )\\\\\\\
435 if type( _sDir ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
436 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sDir ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
437 end\\\\\\\
438 if not fs.isDir( _sDir ) then\\\\\\\
439 error( \\\\\\\"Not a directory\\\\\\\", 2 )\\\\\\\
440 end\\\\\\\
441 sDir = _sDir\\\\\\\
442end\\\\\\\
443\\\\\\\
444function shell.path()\\\\\\\
445 return sPath\\\\\\\
446end\\\\\\\
447\\\\\\\
448function shell.setPath( _sPath )\\\\\\\
449 if type( _sPath ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
450 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sPath ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
451 end\\\\\\\
452 sPath = _sPath\\\\\\\
453end\\\\\\\
454\\\\\\\
455function shell.resolve( _sPath )\\\\\\\
456 if type( _sPath ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
457 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sPath ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
458 end\\\\\\\
459 local sStartChar = string.sub( _sPath, 1, 1 )\\\\\\\
460 if sStartChar == \\\\\\\"/\\\\\\\" or sStartChar == \\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\
461 return fs.combine( \\\\\\\"\\\\\\\", _sPath )\\\\\\\
462 else\\\\\\\
463 return fs.combine( sDir, _sPath )\\\\\\\
464 end\\\\\\\
465end\\\\\\\
466\\\\\\\
467local function pathWithExtension( _sPath, _sExt )\\\\\\\
468 local nLen = #sPath\\\\\\\
469 local sEndChar = string.sub( _sPath, nLen, nLen )\\\\\\\
470 -- Remove any trailing slashes so we can add an extension to the path safely\\\\\\\
471 if sEndChar == \\\\\\\"/\\\\\\\" or sEndChar == \\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\
472 _sPath = string.sub( _sPath, 1, nLen - 1 )\\\\\\\
473 end\\\\\\\
474 return _sPath .. \\\\\\\".\\\\\\\" .. _sExt\\\\\\\
475end\\\\\\\
476\\\\\\\
477function shell.resolveProgram( _sCommand )\\\\\\\
478 if type( _sCommand ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
479 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sCommand ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
480 end\\\\\\\
481 -- Substitute aliases firsts\\\\\\\
482 if tAliases[ _sCommand ] ~= nil then\\\\\\\
483 _sCommand = tAliases[ _sCommand ]\\\\\\\
484 end\\\\\\\
485\\\\\\\
486 -- If the path is a global path, use it directly\\\\\\\
487 local sStartChar = string.sub( _sCommand, 1, 1 )\\\\\\\
488 if sStartChar == \\\\\\\"/\\\\\\\" or sStartChar == \\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\
489 local sPath = fs.combine( \\\\\\\"\\\\\\\", _sCommand )\\\\\\\
490 if fs.exists( sPath ) and not fs.isDir( sPath ) then\\\\\\\
491 return sPath\\\\\\\
492 else\\\\\\\
493 local sPathLua = pathWithExtension( sPath, \\\\\\\"lua\\\\\\\" )\\\\\\\
494 if fs.exists( sPathLua ) and not fs.isDir( sPathLua ) then\\\\\\\
495 return sPathLua\\\\\\\
496 end\\\\\\\
497 end\\\\\\\
498 return nil\\\\\\\
499 end\\\\\\\
500 \\\\\\\
501 -- Otherwise, look on the path variable\\\\\\\
502 for sPath in string.gmatch(sPath, \\\\\\\"[^:]+\\\\\\\") do\\\\\\\
503 sPath = fs.combine( shell.resolve( sPath ), _sCommand )\\\\\\\
504 if fs.exists( sPath ) and not fs.isDir( sPath ) then\\\\\\\
505 return sPath\\\\\\\
506 else\\\\\\\
507 local sPathLua = pathWithExtension( sPath, \\\\\\\"lua\\\\\\\" )\\\\\\\
508 if fs.exists( sPathLua ) and not fs.isDir( sPathLua ) then\\\\\\\
509 return sPathLua\\\\\\\
510 end\\\\\\\
511 end\\\\\\\
512 end\\\\\\\
513 \\\\\\\
514 -- Not found\\\\\\\
515 return nil\\\\\\\
516end\\\\\\\
517\\\\\\\
518function shell.programs( _bIncludeHidden )\\\\\\\
519 local tItems = {}\\\\\\\
520 \\\\\\\
521 -- Add programs from the path\\\\\\\
522 for sPath in string.gmatch(sPath, \\\\\\\"[^:]+\\\\\\\") do\\\\\\\
523 sPath = shell.resolve( sPath )\\\\\\\
524 if fs.isDir( sPath ) then\\\\\\\
525 local tList = fs.list( sPath )\\\\\\\
526 for n=1,#tList do\\\\\\\
527 local sFile = tList[n]\\\\\\\
528 if not fs.isDir( fs.combine( sPath, sFile ) ) and\\\\\\\
529 (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \\\\\\\".\\\\\\\") then\\\\\\\
530 if #sFile > 4 and sFile:sub(-4) == \\\\\\\".lua\\\\\\\" then\\\\\\\
531 sFile = sFile:sub(1,-5)\\\\\\\
532 end\\\\\\\
533 tItems[ sFile ] = true\\\\\\\
534 end\\\\\\\
535 end\\\\\\\
536 end\\\\\\\
537 end \\\\\\\
538\\\\\\\
539 -- Sort and return\\\\\\\
540 local tItemList = {}\\\\\\\
541 for sItem, b in pairs( tItems ) do\\\\\\\
542 table.insert( tItemList, sItem )\\\\\\\
543 end\\\\\\\
544 table.sort( tItemList )\\\\\\\
545 return tItemList\\\\\\\
546end\\\\\\\
547\\\\\\\
548local function completeProgram( sLine )\\\\\\\
549 if #sLine > 0 and string.sub( sLine, 1, 1 ) == \\\\\\\"/\\\\\\\" then\\\\\\\
550 -- Add programs from the root\\\\\\\
551 return fs.complete( sLine, \\\\\\\"\\\\\\\", true, false )\\\\\\\
552\\\\\\\
553 else\\\\\\\
554 local tResults = {}\\\\\\\
555 local tSeen = {}\\\\\\\
556\\\\\\\
557 -- Add aliases\\\\\\\
558 for sAlias, sCommand in pairs( tAliases ) do\\\\\\\
559 if #sAlias > #sLine and string.sub( sAlias, 1, #sLine ) == sLine then\\\\\\\
560 local sResult = string.sub( sAlias, #sLine + 1 )\\\\\\\
561 if not tSeen[ sResult ] then\\\\\\\
562 table.insert( tResults, sResult )\\\\\\\
563 tSeen[ sResult ] = true\\\\\\\
564 end\\\\\\\
565 end\\\\\\\
566 end\\\\\\\
567\\\\\\\
568 -- Add programs from the path\\\\\\\
569 local tPrograms = shell.programs()\\\\\\\
570 for n=1,#tPrograms do\\\\\\\
571 local sProgram = tPrograms[n]\\\\\\\
572 if #sProgram > #sLine and string.sub( sProgram, 1, #sLine ) == sLine then\\\\\\\
573 local sResult = string.sub( sProgram, #sLine + 1 )\\\\\\\
574 if not tSeen[ sResult ] then\\\\\\\
575 table.insert( tResults, sResult )\\\\\\\
576 tSeen[ sResult ] = true\\\\\\\
577 end\\\\\\\
578 end\\\\\\\
579 end\\\\\\\
580\\\\\\\
581 -- Sort and return\\\\\\\
582 table.sort( tResults )\\\\\\\
583 return tResults\\\\\\\
584 end\\\\\\\
585end\\\\\\\
586\\\\\\\
587local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousParts )\\\\\\\
588 local tInfo = tCompletionInfo[ sProgram ]\\\\\\\
589 if tInfo then\\\\\\\
590 return tInfo.fnComplete( shell, nArgument, sPart, tPreviousParts )\\\\\\\
591 end\\\\\\\
592 return nil\\\\\\\
593end\\\\\\\
594\\\\\\\
595function shell.complete( sLine )\\\\\\\
596 if type( sLine ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
597 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( sLine ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
598 end\\\\\\\
599 if #sLine > 0 then\\\\\\\
600 local tWords = tokenise( sLine )\\\\\\\
601 local nIndex = #tWords\\\\\\\
602 if string.sub( sLine, #sLine, #sLine ) == \\\\\\\" \\\\\\\" then\\\\\\\
603 nIndex = nIndex + 1\\\\\\\
604 end\\\\\\\
605 if nIndex == 1 then\\\\\\\
606 local sBit = tWords[1] or \\\\\\\"\\\\\\\"\\\\\\\
607 local sPath = shell.resolveProgram( sBit )\\\\\\\
608 if tCompletionInfo[ sPath ] then\\\\\\\
609 return { \\\\\\\" \\\\\\\" }\\\\\\\
610 else\\\\\\\
611 local tResults = completeProgram( sBit )\\\\\\\
612 for n=1,#tResults do\\\\\\\
613 local sResult = tResults[n]\\\\\\\
614 local sPath = shell.resolveProgram( sBit .. sResult )\\\\\\\
615 if tCompletionInfo[ sPath ] then\\\\\\\
616 tResults[n] = sResult .. \\\\\\\" \\\\\\\"\\\\\\\
617 end\\\\\\\
618 end\\\\\\\
619 return tResults\\\\\\\
620 end\\\\\\\
621\\\\\\\
622 elseif nIndex > 1 then\\\\\\\
623 local sPath = shell.resolveProgram( tWords[1] )\\\\\\\
624 local sPart = tWords[nIndex] or \\\\\\\"\\\\\\\"\\\\\\\
625 local tPreviousParts = tWords\\\\\\\
626 tPreviousParts[nIndex] = nil\\\\\\\
627 return completeProgramArgument( sPath , nIndex - 1, sPart, tPreviousParts )\\\\\\\
628\\\\\\\
629 end\\\\\\\
630 end\\\\\\\
631 return nil\\\\\\\
632end\\\\\\\
633\\\\\\\
634function shell.completeProgram( sProgram )\\\\\\\
635 if type( sProgram ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
636 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( sProgram ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
637 end\\\\\\\
638 return completeProgram( sProgram )\\\\\\\
639end\\\\\\\
640\\\\\\\
641function shell.setCompletionFunction( sProgram, fnComplete )\\\\\\\
642 if type( sProgram ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
643 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( sProgram ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
644 end\\\\\\\
645 if type( fnComplete ) ~= \\\\\\\"function\\\\\\\" then\\\\\\\
646 error( \\\\\\\"bad argument #2 (expected function, got \\\\\\\" .. type( fnComplete ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
647 end\\\\\\\
648 tCompletionInfo[ sProgram ] = {\\\\\\\
649 fnComplete = fnComplete\\\\\\\
650 }\\\\\\\
651end\\\\\\\
652\\\\\\\
653function shell.getCompletionInfo()\\\\\\\
654 return tCompletionInfo\\\\\\\
655end\\\\\\\
656\\\\\\\
657function shell.getRunningProgram()\\\\\\\
658 if #tProgramStack > 0 then\\\\\\\
659 return tProgramStack[#tProgramStack]\\\\\\\
660 end\\\\\\\
661 return nil\\\\\\\
662end\\\\\\\
663\\\\\\\
664function shell.setAlias( _sCommand, _sProgram )\\\\\\\
665 if type( _sCommand ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
666 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sCommand ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
667 end\\\\\\\
668 if type( _sProgram ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
669 error( \\\\\\\"bad argument #2 (expected string, got \\\\\\\" .. type( _sProgram ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
670 end\\\\\\\
671 tAliases[ _sCommand ] = _sProgram\\\\\\\
672end\\\\\\\
673\\\\\\\
674function shell.clearAlias( _sCommand )\\\\\\\
675 if type( _sCommand ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
676 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sCommand ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
677 end\\\\\\\
678 tAliases[ _sCommand ] = nil\\\\\\\
679end\\\\\\\
680\\\\\\\
681function shell.aliases()\\\\\\\
682 -- Copy aliases\\\\\\\
683 local tCopy = {}\\\\\\\
684 for sAlias, sCommand in pairs( tAliases ) do\\\\\\\
685 tCopy[sAlias] = sCommand\\\\\\\
686 end\\\\\\\
687 return tCopy\\\\\\\
688end\\\\\\\
689\\\\\\\
690if process then\\\\\\\
691 function shell.launchProcess( ... )\\\\\\\
692 local tWords = tokenise( ... )\\\\\\\
693 local sCommand = tWords[1]\\\\\\\
694 if sCommand then\\\\\\\
695 local sPath = shell.resolveProgram( sCommand )\\\\\\\
696 if sPath == \\\\\\\"system/bin/sh\\\\\\\" then\\\\\\\
697 return process.launch( createShellEnv( \\\\\\\"rom/programs\\\\\\\" ), sPath, table.unpack( tWords, 2 ) )\\\\\\\
698 elseif sPath ~= nil then\\\\\\\
699 return process.launch( createShellEnv( \\\\\\\"rom/programs\\\\\\\" ), \\\\\\\"rom/programs/shell.lua\\\\\\\", sCommand, table.unpack( tWords, 2 ) )\\\\\\\
700 else\\\\\\\
701 printError( \\\\\\\"No such program\\\\\\\" )\\\\\\\
702 end\\\\\\\
703 end\\\\\\\
704 end\\\\\\\
705\\\\\\\
706 function shell.setProcessFocus( nID )\\\\\\\
707 if type( nID ) ~= \\\\\\\"number\\\\\\\" then\\\\\\\
708 error( \\\\\\\"bad argument #1 (expected number, got \\\\\\\" .. type( nID ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
709 end\\\\\\\
710 process.setFocus( nID )\\\\\\\
711 end\\\\\\\
712end\\\\\\\
713\\\\\\\
714local tArgs = { ... }\\\\\\\
715if #tArgs > 0 then\\\\\\\
716 -- \\\\\\\"shell x y z\\\\\\\"\\\\\\\
717 -- Run the program specified on the commandline\\\\\\\
718 shell.run( ... )\\\\\\\
719\\\\\\\
720else\\\\\\\
721 -- \\\\\\\"shell\\\\\\\"\\\\\\\
722 -- Print the header\\\\\\\
723 term.setBackgroundColor( bgColour )\\\\\\\
724 term.setTextColour( promptColour )\\\\\\\
725 print( os.version() )\\\\\\\
726 term.setTextColour( textColour )\\\\\\\
727\\\\\\\
728 -- Run the startup program\\\\\\\
729 if parentShell == nil then\\\\\\\
730 shell.run( \\\\\\\"/rom/startup.lua\\\\\\\" )\\\\\\\
731 end\\\\\\\
732 sPath = sPath..\\\\\\\":/bin\\\\\\\"\\\\\\\
733\\\\\\\
734 -- Read commands and execute them\\\\\\\
735 local tCommandHistory = {}\\\\\\\
736 while not bExit do\\\\\\\
737 term.redirect( parentTerm )\\\\\\\
738 term.setBackgroundColor( bgColour )\\\\\\\
739 term.setTextColour( promptColour )\\\\\\\
740 write( shell.dir() .. \\\\\\\"> \\\\\\\" )\\\\\\\
741 term.setTextColour( textColour )\\\\\\\
742\\\\\\\
743\\\\\\\
744 local sLine\\\\\\\
745 if settings.get( \\\\\\\"shell.autocomplete\\\\\\\" ) then\\\\\\\
746 sLine = read( nil, tCommandHistory, shell.complete )\\\\\\\
747 else\\\\\\\
748 sLine = read( nil, tCommandHistory )\\\\\\\
749 end\\\\\\\
750 if sLine:match(\\\\\\\"%S\\\\\\\") and tCommandHistory[#tCommandHistory] ~= sLine then\\\\\\\
751 table.insert( tCommandHistory, sLine )\\\\\\\
752 end\\\\\\\
753 shell.run( sLine )\\\\\\\
754 end\\\\\\\
755end\\\"\",\
756 \"F:sh\",\
757 \"\\\"\\\\\\\
758local multishell = multishell\\\\\\\
759local parentShell = shell\\\\\\\
760local parentTerm = term.current()\\\\\\\
761\\\\\\\
762if multishell then\\\\\\\
763 multishell.setTitle( multishell.getCurrent(), \\\\\\\"shell\\\\\\\" )\\\\\\\
764end\\\\\\\
765\\\\\\\
766local bExit = false\\\\\\\
767local sDir = (parentShell and parentShell.dir()) or \\\\\\\"\\\\\\\"\\\\\\\
768local sPath = (parentShell and parentShell.path()) or \\\\\\\".:/rom/programs\\\\\\\"\\\\\\\
769local tAliases = (parentShell and parentShell.aliases()) or {}\\\\\\\
770local tCompletionInfo = (parentShell and parentShell.getCompletionInfo()) or {}\\\\\\\
771local tProgramStack = {}\\\\\\\
772\\\\\\\
773local shell = {}\\\\\\\
774local function createShellEnv( sDir )\\\\\\\
775 local tEnv = {}\\\\\\\
776 tEnv[ \\\\\\\"shell\\\\\\\" ] = shell\\\\\\\
777 tEnv[ \\\\\\\"multishell\\\\\\\" ] = multishell\\\\\\\
778\\\\\\\
779 local package = {}\\\\\\\
780 package.loaded = {\\\\\\\
781 _G = _G,\\\\\\\
782 bit32 = bit32,\\\\\\\
783 coroutine = coroutine,\\\\\\\
784 math = math,\\\\\\\
785 package = package,\\\\\\\
786 string = string,\\\\\\\
787 table = table,\\\\\\\
788 }\\\\\\\
789\\\\009package.standard_libraries = {}\\\\\\\
790\\\\009package.standard_libraries.stdlib = \\\\\\\"/lib/libstdlua.2.so\\\\\\\"\\\\\\\
791\\\\009package.standard_libraries.UI = \\\\\\\"/lib/libuser.2.so\\\\\\\"\\\\\\\
792\\\\009package.standard_libraries.debug = \\\\\\\"/lib/libdebug.1.so\\\\\\\"\\\\\\\
793\\\\009package.standard_libraries.cryptlib = \\\\\\\"/lib/libcrypt.1.so\\\\\\\"\\\\\\\
794\\\\009package.standard_libraries.dism = \\\\\\\"/lib/libdism.1.so\\\\\\\"\\\\\\\
795 package.path = \\\\\\\"?;?.lua;?/init.lua;/rom/modules/main/?;/rom/modules/main/?.lua;/rom/modules/main/?/init.lua\\\\\\\"\\\\\\\
796 if turtle then\\\\\\\
797 package.path = package.path..\\\\\\\";/rom/modules/turtle/?;/rom/modules/turtle/?.lua;/rom/modules/turtle/?/init.lua\\\\\\\"\\\\\\\
798 elseif command then\\\\\\\
799 package.path = package.path..\\\\\\\";/rom/modules/command/?;/rom/modules/command/?.lua;/rom/modules/command/?/init.lua\\\\\\\"\\\\\\\
800 end\\\\\\\
801 package.config = \\\\\\\"/\\\\\\\\n;\\\\\\\\n?\\\\\\\\n!\\\\\\\\n-\\\\\\\"\\\\\\\
802 package.preload = {}\\\\\\\
803 package.loaders = {\\\\\\\
804 function( name )\\\\\\\
805 if package.preload[name] then\\\\\\\
806 return package.preload[name]\\\\\\\
807 else\\\\\\\
808 return nil, \\\\\\\"no field package.preload['\\\\\\\" .. name .. \\\\\\\"']\\\\\\\"\\\\\\\
809 end\\\\\\\
810 end,\\\\\\\
811 function( name )\\\\\\\
812 local fname = string.gsub(name, \\\\\\\"%.\\\\\\\", \\\\\\\"/\\\\\\\")\\\\\\\
813 local sError = \\\\\\\"\\\\\\\"\\\\\\\
814 for pattern in string.gmatch(package.path, \\\\\\\"[^;]+\\\\\\\") do\\\\\\\
815 local sPath = string.gsub(pattern, \\\\\\\"%?\\\\\\\", fname)\\\\\\\
816 if sPath:sub(1,1) ~= \\\\\\\"/\\\\\\\" then\\\\\\\
817 sPath = fs.combine(sDir, sPath)\\\\\\\
818 end\\\\\\\
819 if fs.exists(sPath) and not fs.isDir(sPath) then\\\\\\\
820 local fnFile, sError = loadfile( sPath, tEnv )\\\\\\\
821 if fnFile then\\\\\\\
822 return fnFile, sPath\\\\\\\
823 else\\\\\\\
824 return nil, sError\\\\\\\
825 end\\\\\\\
826 else\\\\\\\
827 if #sError > 0 then\\\\\\\
828 sError = sError .. \\\\\\\"\\\\\\\\n\\\\\\\"\\\\\\\
829 end\\\\\\\
830 sError = sError .. \\\\\\\"no file '\\\\\\\" .. sPath .. \\\\\\\"'\\\\\\\"\\\\\\\
831 end\\\\\\\
832 end\\\\\\\
833 return nil, sError\\\\\\\
834 end\\\\\\\
835 }\\\\\\\
836\\\\\\\
837 local sentinel = {}\\\\\\\
838 local function require( name )\\\\\\\
839 if type( name ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
840 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( name ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
841 end\\\\\\\
842 if package.loaded[name] == sentinel then\\\\\\\
843 error(\\\\\\\"Loop detected requiring '\\\\\\\" .. name .. \\\\\\\"'\\\\\\\", 0)\\\\\\\
844 end\\\\\\\
845 if package.loaded[name] then\\\\\\\
846 return package.loaded[name]\\\\\\\
847 end\\\\\\\
848\\\\\\\
849 local sError = \\\\\\\"Error loading module '\\\\\\\" .. name .. \\\\\\\"':\\\\\\\"\\\\\\\
850 for n,searcher in ipairs(package.loaders) do\\\\\\\
851 local loader, err = searcher(name)\\\\\\\
852 if loader then\\\\\\\
853 package.loaded[name] = sentinel\\\\\\\
854 local result = loader( err )\\\\\\\
855 if result ~= nil then\\\\\\\
856 package.loaded[name] = result\\\\\\\
857 return result\\\\\\\
858 else\\\\\\\
859 package.loaded[name] = true\\\\\\\
860 return true\\\\\\\
861 end\\\\\\\
862 else\\\\\\\
863 sError = sError .. \\\\\\\"\\\\\\\\n\\\\\\\" .. err\\\\\\\
864 end\\\\\\\
865 end\\\\\\\
866 error(sError, 2)\\\\\\\
867 end\\\\\\\
868\\\\\\\
869 tEnv[\\\\\\\"package\\\\\\\"] = package\\\\\\\
870 tEnv[\\\\\\\"require\\\\\\\"] = require\\\\\\\
871\\\\\\\
872 return tEnv\\\\\\\
873end\\\\\\\
874\\\\\\\
875-- Colours\\\\\\\
876local promptColour, textColour, bgColour\\\\\\\
877if term.isColour() then\\\\\\\
878 promptColour = colours.yellow\\\\\\\
879 textColour = colours.white\\\\\\\
880 bgColour = colours.black\\\\\\\
881else\\\\\\\
882 promptColour = colours.white\\\\\\\
883 textColour = colours.white\\\\\\\
884 bgColour = colours.black\\\\\\\
885end\\\\\\\
886\\\\\\\
887local function run( _sCommand, ... )\\\\\\\
888 local sPath = shell.resolveProgram( _sCommand )\\\\\\\
889 if sPath ~= nil then\\\\\\\
890 tProgramStack[#tProgramStack + 1] = sPath\\\\\\\
891 if multishell then\\\\\\\
892 local sTitle = fs.getName( sPath )\\\\\\\
893 if sTitle:sub(-4) == \\\\\\\".lua\\\\\\\" then\\\\\\\
894 sTitle = sTitle:sub(1,-5)\\\\\\\
895 end\\\\\\\
896 multishell.setTitle( multishell.getCurrent(), sTitle )\\\\\\\
897 end\\\\\\\
898 local sDir = fs.getDir( sPath )\\\\\\\
899 local result = os.run( createShellEnv( sDir ), sPath, ... )\\\\\\\
900 tProgramStack[#tProgramStack] = nil\\\\\\\
901 if multishell then\\\\\\\
902 if #tProgramStack > 0 then\\\\\\\
903 local sTitle = fs.getName( tProgramStack[#tProgramStack] )\\\\\\\
904 if sTitle:sub(-4) == \\\\\\\".lua\\\\\\\" then\\\\\\\
905 sTitle = sTitle:sub(1,-5)\\\\\\\
906 end\\\\\\\
907 multishell.setTitle( multishell.getCurrent(), sTitle )\\\\\\\
908 else\\\\\\\
909 multishell.setTitle( multishell.getCurrent(), \\\\\\\"shell\\\\\\\" )\\\\\\\
910 end\\\\\\\
911 end\\\\\\\
912 return result\\\\\\\
913 else\\\\\\\
914 printError( \\\\\\\"No such program\\\\\\\" )\\\\\\\
915 return false\\\\\\\
916 end\\\\\\\
917end\\\\\\\
918\\\\\\\
919local function tokenise( ... )\\\\\\\
920 local sLine = table.concat( { ... }, \\\\\\\" \\\\\\\" )\\\\\\\
921 local tWords = {}\\\\\\\
922 local bQuoted = false\\\\\\\
923 for match in string.gmatch( sLine .. \\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\", \\\\\\\"(.-)\\\\\\\\\\\\\\\"\\\\\\\" ) do\\\\\\\
924 if bQuoted then\\\\\\\
925 table.insert( tWords, match )\\\\\\\
926 else\\\\\\\
927 for m in string.gmatch( match, \\\\\\\"[^ \\\\\\\\t]+\\\\\\\" ) do\\\\\\\
928 table.insert( tWords, m )\\\\\\\
929 end\\\\\\\
930 end\\\\\\\
931 bQuoted = not bQuoted\\\\\\\
932 end\\\\\\\
933 return tWords\\\\\\\
934end\\\\\\\
935\\\\\\\
936-- Install shell API\\\\\\\
937function shell.run( ... )\\\\\\\
938 local tWords = tokenise( ... )\\\\\\\
939 local sCommand = tWords[1]\\\\\\\
940 if sCommand then\\\\\\\
941 return run( sCommand, table.unpack( tWords, 2 ) )\\\\\\\
942 end\\\\\\\
943 return false\\\\\\\
944end\\\\\\\
945\\\\\\\
946function shell.exit()\\\\\\\
947 bExit = true\\\\\\\
948end\\\\\\\
949\\\\\\\
950function shell.dir()\\\\\\\
951 return sDir\\\\\\\
952end\\\\\\\
953\\\\\\\
954function shell.setDir( _sDir )\\\\\\\
955 if type( _sDir ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
956 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sDir ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
957 end\\\\\\\
958 if not fs.isDir( _sDir ) then\\\\\\\
959 error( \\\\\\\"Not a directory\\\\\\\", 2 )\\\\\\\
960 end\\\\\\\
961 sDir = _sDir\\\\\\\
962end\\\\\\\
963\\\\\\\
964function shell.path()\\\\\\\
965 return sPath\\\\\\\
966end\\\\\\\
967\\\\\\\
968function shell.setPath( _sPath )\\\\\\\
969 if type( _sPath ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
970 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sPath ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
971 end\\\\\\\
972 sPath = _sPath\\\\\\\
973end\\\\\\\
974\\\\\\\
975function shell.resolve( _sPath )\\\\\\\
976 if type( _sPath ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
977 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sPath ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
978 end\\\\\\\
979 local sStartChar = string.sub( _sPath, 1, 1 )\\\\\\\
980 if sStartChar == \\\\\\\"/\\\\\\\" or sStartChar == \\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\
981 return fs.combine( \\\\\\\"\\\\\\\", _sPath )\\\\\\\
982 else\\\\\\\
983 return fs.combine( sDir, _sPath )\\\\\\\
984 end\\\\\\\
985end\\\\\\\
986\\\\\\\
987local function pathWithExtension( _sPath, _sExt )\\\\\\\
988 local nLen = #sPath\\\\\\\
989 local sEndChar = string.sub( _sPath, nLen, nLen )\\\\\\\
990 -- Remove any trailing slashes so we can add an extension to the path safely\\\\\\\
991 if sEndChar == \\\\\\\"/\\\\\\\" or sEndChar == \\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\
992 _sPath = string.sub( _sPath, 1, nLen - 1 )\\\\\\\
993 end\\\\\\\
994 return _sPath .. \\\\\\\".\\\\\\\" .. _sExt\\\\\\\
995end\\\\\\\
996\\\\\\\
997function shell.resolveProgram( _sCommand )\\\\\\\
998 if type( _sCommand ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
999 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sCommand ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1000 end\\\\\\\
1001 -- Substitute aliases firsts\\\\\\\
1002 if tAliases[ _sCommand ] ~= nil then\\\\\\\
1003 _sCommand = tAliases[ _sCommand ]\\\\\\\
1004 end\\\\\\\
1005\\\\\\\
1006 -- If the path is a global path, use it directly\\\\\\\
1007 local sStartChar = string.sub( _sCommand, 1, 1 )\\\\\\\
1008 if sStartChar == \\\\\\\"/\\\\\\\" or sStartChar == \\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\
1009 local sPath = fs.combine( \\\\\\\"\\\\\\\", _sCommand )\\\\\\\
1010 if fs.exists( sPath ) and not fs.isDir( sPath ) then\\\\\\\
1011 return sPath\\\\\\\
1012 else\\\\\\\
1013 local sPathLua = pathWithExtension( sPath, \\\\\\\"lua\\\\\\\" )\\\\\\\
1014 if fs.exists( sPathLua ) and not fs.isDir( sPathLua ) then\\\\\\\
1015 return sPathLua\\\\\\\
1016 end\\\\\\\
1017 end\\\\\\\
1018 return nil\\\\\\\
1019 end\\\\\\\
1020 \\\\\\\
1021 -- Otherwise, look on the path variable\\\\\\\
1022 for sPath in string.gmatch(sPath, \\\\\\\"[^:]+\\\\\\\") do\\\\\\\
1023 sPath = fs.combine( shell.resolve( sPath ), _sCommand )\\\\\\\
1024 if fs.exists( sPath ) and not fs.isDir( sPath ) then\\\\\\\
1025 return sPath\\\\\\\
1026 else\\\\\\\
1027 local sPathLua = pathWithExtension( sPath, \\\\\\\"lua\\\\\\\" )\\\\\\\
1028 if fs.exists( sPathLua ) and not fs.isDir( sPathLua ) then\\\\\\\
1029 return sPathLua\\\\\\\
1030 end\\\\\\\
1031 end\\\\\\\
1032 end\\\\\\\
1033 \\\\\\\
1034 -- Not found\\\\\\\
1035 return nil\\\\\\\
1036end\\\\\\\
1037\\\\\\\
1038function shell.programs( _bIncludeHidden )\\\\\\\
1039 local tItems = {}\\\\\\\
1040 \\\\\\\
1041 -- Add programs from the path\\\\\\\
1042 for sPath in string.gmatch(sPath, \\\\\\\"[^:]+\\\\\\\") do\\\\\\\
1043 sPath = shell.resolve( sPath )\\\\\\\
1044 if fs.isDir( sPath ) then\\\\\\\
1045 local tList = fs.list( sPath )\\\\\\\
1046 for n=1,#tList do\\\\\\\
1047 local sFile = tList[n]\\\\\\\
1048 if not fs.isDir( fs.combine( sPath, sFile ) ) and\\\\\\\
1049 (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \\\\\\\".\\\\\\\") then\\\\\\\
1050 if #sFile > 4 and sFile:sub(-4) == \\\\\\\".lua\\\\\\\" then\\\\\\\
1051 sFile = sFile:sub(1,-5)\\\\\\\
1052 end\\\\\\\
1053 tItems[ sFile ] = true\\\\\\\
1054 end\\\\\\\
1055 end\\\\\\\
1056 end\\\\\\\
1057 end \\\\\\\
1058\\\\\\\
1059 -- Sort and return\\\\\\\
1060 local tItemList = {}\\\\\\\
1061 for sItem, b in pairs( tItems ) do\\\\\\\
1062 table.insert( tItemList, sItem )\\\\\\\
1063 end\\\\\\\
1064 table.sort( tItemList )\\\\\\\
1065 return tItemList\\\\\\\
1066end\\\\\\\
1067\\\\\\\
1068local function completeProgram( sLine )\\\\\\\
1069 if #sLine > 0 and string.sub( sLine, 1, 1 ) == \\\\\\\"/\\\\\\\" then\\\\\\\
1070 -- Add programs from the root\\\\\\\
1071 return fs.complete( sLine, \\\\\\\"\\\\\\\", true, false )\\\\\\\
1072\\\\\\\
1073 else\\\\\\\
1074 local tResults = {}\\\\\\\
1075 local tSeen = {}\\\\\\\
1076\\\\\\\
1077 -- Add aliases\\\\\\\
1078 for sAlias, sCommand in pairs( tAliases ) do\\\\\\\
1079 if #sAlias > #sLine and string.sub( sAlias, 1, #sLine ) == sLine then\\\\\\\
1080 local sResult = string.sub( sAlias, #sLine + 1 )\\\\\\\
1081 if not tSeen[ sResult ] then\\\\\\\
1082 table.insert( tResults, sResult )\\\\\\\
1083 tSeen[ sResult ] = true\\\\\\\
1084 end\\\\\\\
1085 end\\\\\\\
1086 end\\\\\\\
1087\\\\\\\
1088 -- Add programs from the path\\\\\\\
1089 local tPrograms = shell.programs()\\\\\\\
1090 for n=1,#tPrograms do\\\\\\\
1091 local sProgram = tPrograms[n]\\\\\\\
1092 if #sProgram > #sLine and string.sub( sProgram, 1, #sLine ) == sLine then\\\\\\\
1093 local sResult = string.sub( sProgram, #sLine + 1 )\\\\\\\
1094 if not tSeen[ sResult ] then\\\\\\\
1095 table.insert( tResults, sResult )\\\\\\\
1096 tSeen[ sResult ] = true\\\\\\\
1097 end\\\\\\\
1098 end\\\\\\\
1099 end\\\\\\\
1100\\\\\\\
1101 -- Sort and return\\\\\\\
1102 table.sort( tResults )\\\\\\\
1103 return tResults\\\\\\\
1104 end\\\\\\\
1105end\\\\\\\
1106\\\\\\\
1107local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousParts )\\\\\\\
1108 local tInfo = tCompletionInfo[ sProgram ]\\\\\\\
1109 if tInfo then\\\\\\\
1110 return tInfo.fnComplete( shell, nArgument, sPart, tPreviousParts )\\\\\\\
1111 end\\\\\\\
1112 return nil\\\\\\\
1113end\\\\\\\
1114\\\\\\\
1115function shell.complete( sLine )\\\\\\\
1116 if type( sLine ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
1117 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( sLine ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1118 end\\\\\\\
1119 if #sLine > 0 then\\\\\\\
1120 local tWords = tokenise( sLine )\\\\\\\
1121 local nIndex = #tWords\\\\\\\
1122 if string.sub( sLine, #sLine, #sLine ) == \\\\\\\" \\\\\\\" then\\\\\\\
1123 nIndex = nIndex + 1\\\\\\\
1124 end\\\\\\\
1125 if nIndex == 1 then\\\\\\\
1126 local sBit = tWords[1] or \\\\\\\"\\\\\\\"\\\\\\\
1127 local sPath = shell.resolveProgram( sBit )\\\\\\\
1128 if tCompletionInfo[ sPath ] then\\\\\\\
1129 return { \\\\\\\" \\\\\\\" }\\\\\\\
1130 else\\\\\\\
1131 local tResults = completeProgram( sBit )\\\\\\\
1132 for n=1,#tResults do\\\\\\\
1133 local sResult = tResults[n]\\\\\\\
1134 local sPath = shell.resolveProgram( sBit .. sResult )\\\\\\\
1135 if tCompletionInfo[ sPath ] then\\\\\\\
1136 tResults[n] = sResult .. \\\\\\\" \\\\\\\"\\\\\\\
1137 end\\\\\\\
1138 end\\\\\\\
1139 return tResults\\\\\\\
1140 end\\\\\\\
1141\\\\\\\
1142 elseif nIndex > 1 then\\\\\\\
1143 local sPath = shell.resolveProgram( tWords[1] )\\\\\\\
1144 local sPart = tWords[nIndex] or \\\\\\\"\\\\\\\"\\\\\\\
1145 local tPreviousParts = tWords\\\\\\\
1146 tPreviousParts[nIndex] = nil\\\\\\\
1147 return completeProgramArgument( sPath , nIndex - 1, sPart, tPreviousParts )\\\\\\\
1148\\\\\\\
1149 end\\\\\\\
1150 end\\\\\\\
1151 return nil\\\\\\\
1152end\\\\\\\
1153\\\\\\\
1154function shell.completeProgram( sProgram )\\\\\\\
1155 if type( sProgram ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
1156 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( sProgram ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1157 end\\\\\\\
1158 return completeProgram( sProgram )\\\\\\\
1159end\\\\\\\
1160\\\\\\\
1161function shell.setCompletionFunction( sProgram, fnComplete )\\\\\\\
1162 if type( sProgram ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
1163 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( sProgram ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1164 end\\\\\\\
1165 if type( fnComplete ) ~= \\\\\\\"function\\\\\\\" then\\\\\\\
1166 error( \\\\\\\"bad argument #2 (expected function, got \\\\\\\" .. type( fnComplete ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1167 end\\\\\\\
1168 tCompletionInfo[ sProgram ] = {\\\\\\\
1169 fnComplete = fnComplete\\\\\\\
1170 }\\\\\\\
1171end\\\\\\\
1172\\\\\\\
1173function shell.getCompletionInfo()\\\\\\\
1174 return tCompletionInfo\\\\\\\
1175end\\\\\\\
1176\\\\\\\
1177function shell.getRunningProgram()\\\\\\\
1178 if #tProgramStack > 0 then\\\\\\\
1179 return tProgramStack[#tProgramStack]\\\\\\\
1180 end\\\\\\\
1181 return nil\\\\\\\
1182end\\\\\\\
1183\\\\\\\
1184function shell.setAlias( _sCommand, _sProgram )\\\\\\\
1185 if type( _sCommand ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
1186 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sCommand ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1187 end\\\\\\\
1188 if type( _sProgram ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
1189 error( \\\\\\\"bad argument #2 (expected string, got \\\\\\\" .. type( _sProgram ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1190 end\\\\\\\
1191 tAliases[ _sCommand ] = _sProgram\\\\\\\
1192end\\\\\\\
1193\\\\\\\
1194function shell.clearAlias( _sCommand )\\\\\\\
1195 if type( _sCommand ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
1196 error( \\\\\\\"bad argument #1 (expected string, got \\\\\\\" .. type( _sCommand ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1197 end\\\\\\\
1198 tAliases[ _sCommand ] = nil\\\\\\\
1199end\\\\\\\
1200\\\\\\\
1201function shell.aliases()\\\\\\\
1202 -- Copy aliases\\\\\\\
1203 local tCopy = {}\\\\\\\
1204 for sAlias, sCommand in pairs( tAliases ) do\\\\\\\
1205 tCopy[sAlias] = sCommand\\\\\\\
1206 end\\\\\\\
1207 return tCopy\\\\\\\
1208end\\\\\\\
1209\\\\\\\
1210if multishell then\\\\\\\
1211 function shell.openTab( ... )\\\\\\\
1212 local tWords = tokenise( ... )\\\\\\\
1213 local sCommand = tWords[1]\\\\\\\
1214 if sCommand then\\\\\\\
1215 local sPath = shell.resolveProgram( sCommand )\\\\\\\
1216 if sPath == \\\\\\\"rom/programs/shell.lua\\\\\\\" then\\\\\\\
1217 return multishell.launch( createShellEnv( \\\\\\\"rom/programs\\\\\\\" ), sPath, table.unpack( tWords, 2 ) )\\\\\\\
1218 elseif sPath ~= nil then\\\\\\\
1219 return multishell.launch( createShellEnv( \\\\\\\"rom/programs\\\\\\\" ), \\\\\\\"rom/programs/shell.lua\\\\\\\", sCommand, table.unpack( tWords, 2 ) )\\\\\\\
1220 else\\\\\\\
1221 printError( \\\\\\\"No such program\\\\\\\" )\\\\\\\
1222 end\\\\\\\
1223 end\\\\\\\
1224 end\\\\\\\
1225\\\\\\\
1226 function shell.switchTab( nID )\\\\\\\
1227 if type( nID ) ~= \\\\\\\"number\\\\\\\" then\\\\\\\
1228 error( \\\\\\\"bad argument #1 (expected number, got \\\\\\\" .. type( nID ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
1229 end\\\\\\\
1230 multishell.setFocus( nID )\\\\\\\
1231 end\\\\\\\
1232end\\\\\\\
1233\\\\\\\
1234function shell.executeScript(path)\\\\\\\
1235 if not fs.exists(path) or fs.isDir(path) then\\\\\\\
1236 return \\\\\\\"file does not exist\\\\\\\"\\\\\\\
1237 else\\\\\\\
1238 local t = kernel.iterateFileLines(path)\\\\\\\
1239 if t[1] == \\\\\\\"@ #handler /system/bin/sh\\\\\\\" then\\\\\\\
1240 for _,cmd in pairs(t) do\\\\\\\
1241 shell.run(cmd)\\\\\\\
1242 end\\\\\\\
1243 else\\\\\\\
1244 return \\\\\\\"script header is missing or corrupt\\\\\\\" \\\\\\\
1245 end\\\\\\\
1246 end\\\\\\\
1247end\\\\\\\
1248\\\\\\\
1249local tArgs = { ... }\\\\\\\
1250if #tArgs > 0 then\\\\\\\
1251 -- \\\\\\\"shell x y z\\\\\\\"\\\\\\\
1252 -- Run the program specified on the commandline\\\\\\\
1253 shell.run( ... )\\\\\\\
1254\\\\\\\
1255else\\\\\\\
1256 -- \\\\\\\"shell\\\\\\\"\\\\\\\
1257 -- Print the header\\\\\\\
1258 term.setBackgroundColor( bgColour )\\\\\\\
1259 term.setTextColour( promptColour )\\\\\\\
1260 print( os.version() )\\\\\\\
1261 term.setTextColour( textColour )\\\\\\\
1262\\\\\\\
1263 -- Run the startup program\\\\\\\
1264 if parentShell == nil then\\\\\\\
1265 shell.run( \\\\\\\"/rom/startup.lua\\\\\\\" )\\\\\\\
1266 end\\\\\\\
1267 sPath = sPath..\\\\\\\":/bin\\\\\\\"\\\\\\\
1268\\\\\\\
1269 -- Read commands and execute them\\\\\\\
1270 local tCommandHistory = {}\\\\\\\
1271 while not bExit do\\\\\\\
1272 term.redirect( parentTerm )\\\\\\\
1273 term.setBackgroundColor( bgColour )\\\\\\\
1274 term.setTextColour( promptColour )\\\\\\\
1275\\\\009\\\\009if __DEBUG then\\\\\\\
1276 stdout( \\\\\\\"/\\\\\\\" .. shell.dir() .. \\\\\\\" # \\\\\\\" )\\\\\\\
1277\\\\009\\\\009else\\\\\\\
1278 stdout( \\\\\\\"/\\\\\\\" .. shell.dir() .. \\\\\\\" $ \\\\\\\" )\\\\\\\
1279\\\\009\\\\009end\\\\\\\
1280 term.setTextColour( textColour )\\\\\\\
1281\\\\\\\
1282\\\\\\\
1283 local sLine\\\\\\\
1284 sLine = read( nil, tCommandHistory, shell.complete )\\\\\\\
1285 if sLine:match(\\\\\\\"%S\\\\\\\") and tCommandHistory[#tCommandHistory] ~= sLine then\\\\\\\
1286 table.insert( tCommandHistory, sLine )\\\\\\\
1287 end\\\\\\\
1288 shell.run( sLine )\\\\\\\
1289 end\\\\\\\
1290end\\\"\",\
1291 \"F:systeminfo\",\
1292 \"\\\"print(os.version())\\\\\\\
1293print(\\\\\\\"Path:\\\\\\\" shell.path())\\\\\\\
1294print(\\\\\\\"ID \\\\\\\"..os.getComputerID() or \\\\\\\"N/A\\\\\\\")\\\\\\\
1295print(\\\\\\\"Computer labeled as \\\\\\\"..os.getComputerLabel() or \\\\\\\"N/A\\\\\\\")\\\"\",\
1296 \"F:tree\",\
1297 \"\\\"-- Context: http://www.computercraft.info/forums2/index.php?/topic/44-request-windows-tree-command/\\\\\\\
1298\\\\\\\
1299local tArgs = { ... }\\\\\\\
1300local currentPath = shell.resolve(\\\\\\\".\\\\\\\")\\\\\\\
1301local lineCounter = 0\\\\\\\
1302local pageFlip = false\\\\\\\
1303local askingForHelp = false\\\\\\\
1304\\\\\\\
1305--[[ Process command line arguments ]]\\\\\\\
1306if #tArgs > 1 then -- More than one argument.\\\\\\\
1307 if ( tArgs[1] == string.lower( \\\\\\\"-m\\\\\\\" ) ) or ( tArgs[1] == string.lower( \\\\\\\"-more\\\\\\\" ) ) then\\\\\\\
1308 pageFlip = true\\\\\\\
1309 currentPath = shell.resolve( tArgs[2] )\\\\\\\
1310 elseif ( tArgs[2] == string.lower( \\\\\\\"-m\\\\\\\" ) ) or ( tArgs[2] == string.lower( \\\\\\\"-more\\\\\\\" ) ) then\\\\\\\
1311 pageFlip = true\\\\\\\
1312 currentPath = shell.resolve( tArgs[1] )\\\\\\\
1313 else\\\\\\\
1314 currentPath = shell.resolve( tArgs[1] )\\\\\\\
1315 end\\\\\\\
1316else -- Only one argument.\\\\\\\
1317 if ( tArgs[1] == string.lower( \\\\\\\"-h\\\\\\\" ) ) or ( tArgs[1] == string.lower( \\\\\\\"-help\\\\\\\" ) ) then\\\\\\\
1318 askingForHelp = true\\\\\\\
1319 elseif tArgs[1] ~= nil then\\\\\\\
1320 currentPath = shell.resolve( tArgs[1] )\\\\\\\
1321 end\\\\\\\
1322end\\\\\\\
1323\\\\\\\
1324function printUsage()\\\\\\\
1325 print( \\\\\\\"Usage: tree [-more] [-help] [<DIRECTORY>]\\\\\\\\n\\\\\\\" )\\\\\\\
1326 \\\\\\\
1327 print( \\\\\\\"-m or -more Enable page flipping.\\\\\\\" )\\\\\\\
1328 print( \\\\\\\"-h or -help Show this help.\\\\\\\" )\\\\\\\
1329 print( \\\\\\\"<DIRECTORY> Name of the directory.\\\\\\\" )\\\\\\\
1330 print( \\\\\\\" (Default is current directory)\\\\\\\" )\\\\\\\
1331\\\\009print( \\\\\\\"Made by Espen.\\\\\\\")\\\\\\\
1332end\\\\\\\
1333\\\\\\\
1334function listDir( path, prefix )\\\\\\\
1335 if path == \\\\\\\"\\\\\\\" then path = \\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\" end -- Path of execution.\\\\\\\
1336 \\\\\\\
1337 -- Iterate through every element (file or dir) in the path.\\\\\\\
1338 for k, v in pairs( fs.list( path ) ) do\\\\\\\
1339 ---[[ PAGE-FLIP\\\\\\\
1340 if pageFlip then\\\\\\\
1341 lineCounter = lineCounter + 1\\\\\\\
1342 if lineCounter >= 17 then\\\\\\\
1343 write(\\\\\\\"Press any key to continue\\\\\\\")\\\\\\\
1344 read()\\\\\\\
1345 term.setCursorPos( 1, 1 )\\\\\\\
1346 term.clear()\\\\\\\
1347 lineCounter = 0\\\\\\\
1348 end\\\\\\\
1349 end\\\\\\\
1350 --]]\\\\\\\
1351 -- Print file/dir name.\\\\\\\
1352 print( prefix..\\\\\\\"-- \\\\\\\"..v )\\\\\\\
1353 -- Traverse next directory, if any.\\\\\\\
1354 local nextDir = path..\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\"..v\\\\\\\
1355 if fs.isDir( nextDir ) then listDir( nextDir, prefix..\\\\\\\" |\\\\\\\" ) end\\\\\\\
1356 end\\\\\\\
1357end\\\\\\\
1358\\\\\\\
1359if askingForHelp then\\\\\\\
1360 printUsage()\\\\\\\
1361else\\\\\\\
1362 print( \\\\\\\"Listing directory: \\\\\\\"..currentPath )\\\\\\\
1363 listDir( currentPath, \\\\\\\"|\\\\\\\" )\\\\\\\
1364end\\\"\",\
1365 \"F:tty\",\
1366 \"\\\"local x, y = term.getSize()\\\\\\\
1367print(\\\\\\\"terminal object size is \\\\\\\"..tostring(x)..\\\\\\\"x\\\\\\\"..tostring(y))\\\\\\\
1368\\\"\",\
1369}",
1370 "D:boot",
1371 "{\
1372 \"D:esi\",\
1373 \"{\\\
1374 \\\"F:config.dat\\\",\\\
1375 \\\"\\\\\\\"{\\\\\\\\\\\\\\\
1376 script = \\\\\\\\\\\\\\\"Orbital\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\
1377}\\\\\\\"\\\",\\\
1378 \\\"D:drivers\\\",\\\
1379 \\\"{\\\\\\\
1380 \\\\\\\"F:dmouse.sys\\\\\\\",\\\\\\\
1381 \\\\\\\"\\\\\\\\\\\\\\\"local function handleRegionMouseInput(xx, yy, x1, x2, y1, y2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1382 y0 = y2 or y1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1383 if (xx >= x1 and xx <= x2) then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1384 if (yy >= y1 and yy <= y0) then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1385 return true\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1386 elseif yy == y1 or yy == y0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1387 return true\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1388 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1389 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1390 return false\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1391end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1392\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1393__declare_api(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"peripheral\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"handleMouseInput\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", function(...)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1394 local tArgs = {...}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1395 if #tArgs < 1 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1396 error(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"usage: handleMouseInput(<table describing the minX, maxX, minY and maxY positions of a button>, [more tables like this]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1397 else\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1398 while true do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1399 sleep(0.01)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1400 local a, b, x, y = os.pullEvent(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"mouse_click\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1401 sleep(0.01)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1402 for k,v in ipairs(tArgs) do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1403 local minX = v[1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1404\\\\\\\\\\\\\\\\009local maxX = v[2]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1405\\\\\\\\\\\\\\\\009local minY = v[3]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1406\\\\\\\\\\\\\\\\009local maxY = v[4] or v[3]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1407 if handleRegionMouseInput(x, y, minX, maxX, minY, maxY) then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1408 return k\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1409 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1410 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1411 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1412 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1413end)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1414\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1415return true\\\\\\\\\\\\\\\"\\\\\\\",\\\\\\\
1416 \\\\\\\"F:dvirt.sys\\\\\\\",\\\\\\\
1417 \\\\\\\"\\\\\\\\\\\\\\\"-- Guest Virtualization Driver for Orbital.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1418-- Supports CCEmuX.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1419\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1420if ccemux then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1421 ccemux.attach(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"top\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"wireless_modem\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1422 if __DEBUG then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1423 __declare(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"__DEBUG_REMOTE\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", __kstruct({true}))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1424 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1425 return true\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1426end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1427\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1428return false, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"Compatible hypervisor not detected\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\",\\\\\\\
1429 \\\\\\\"F:ecc.sys\\\\\\\",\\\\\\\
1430 \\\\\\\"\\\\\\\\\\\\\\\"-- Elliptic Curve Cryptography in Computercraft\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1431\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1432local byteTableMT = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1433 __tostring = function(a) return string.char(unpack(a)) end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1434 __index = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1435 toHex = function(self, s) return (\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"%02x\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"):rep(#self):format(unpack(self)) end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1436 isEqual = function(self, t)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1437 if type(t) ~= \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then return false end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1438 if #self ~= #t then return false end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1439 local ret = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1440 for i = 1, #self do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1441 ret = bit32.bor(ret, bit32.bxor(self[i], t[i]))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1442 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1443 return ret == 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1444 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1445 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1446}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1447\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1448-- SHA-256, HMAC and PBKDF2 functions in ComputerCraft\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1449-- By Anavrins\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1450-- For help and details, you can PM me on the CC forums\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1451-- You may use this code in your projects without asking me, as long as credit is given and this header is kept intact\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1452-- http://www.computercraft.info/forums2/index.php?/user/12870-anavrins\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1453-- http://pastebin.com/6UV4qfNF\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1454-- Last update: October 10, 2017\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1455local sha256 = (function()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1456 local mod32 = 2^32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1457 local band = bit32 and bit32.band or bit.band\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1458 local bnot = bit32 and bit32.bnot or bit.bnot\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1459 local bxor = bit32 and bit32.bxor or bit.bxor\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1460 local blshift = bit32 and bit32.lshift or bit.blshift\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1461 local upack = unpack\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1462\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1463 local function rrotate(n, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1464 local s = n/(2^b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1465 local f = s%1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1466 return (s-f) + f*mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1467 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1468 local function brshift(int, by) -- Thanks bit32 for bad rshift\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1469 local s = int / (2^by)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1470 return s - s%1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1471 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1472\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1473 local H = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1474 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1475 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1476 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1477\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1478 local K = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1479 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1480 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1481 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1482 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1483 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1484 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1485 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1486 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1487 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1488\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1489 local function counter(incr)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1490 local t1, t2 = 0, 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1491 if 0xFFFFFFFF - t1 < incr then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1492 t2 = t2 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1493 t1 = incr - (0xFFFFFFFF - t1) - 1 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1494 else t1 = t1 + incr\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1495 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1496 return t2, t1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1497 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1498\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1499 local function BE_toInt(bs, i)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1500 return blshift((bs[i] or 0), 24) + blshift((bs[i+1] or 0), 16) + blshift((bs[i+2] or 0), 8) + (bs[i+3] or 0)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1501 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1502\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1503 local function preprocess(data)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1504 local len = #data\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1505 local proc = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1506 data[#data+1] = 0x80\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1507 while #data%64~=56 do data[#data+1] = 0 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1508 local blocks = math.ceil(#data/64)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1509 for i = 1, blocks do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1510 proc[i] = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1511 for j = 1, 16 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1512 proc[i][j] = BE_toInt(data, 1+((i-1)*64)+((j-1)*4))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1513 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1514 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1515 proc[blocks][15], proc[blocks][16] = counter(len*8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1516 return proc\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1517 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1518\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1519 local function digestblock(w, C)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1520 for j = 17, 64 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1521 local v = w[j-15]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1522 local s0 = bxor(bxor(rrotate(w[j-15], 7), rrotate(w[j-15], 18)), brshift(w[j-15], 3))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1523 local s1 = bxor(bxor(rrotate(w[j-2], 17), rrotate(w[j-2], 19)), brshift(w[j-2], 10))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1524 w[j] = (w[j-16] + s0 + w[j-7] + s1)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1525 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1526 local a, b, c, d, e, f, g, h = upack(C)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1527 for j = 1, 64 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1528 local S1 = bxor(bxor(rrotate(e, 6), rrotate(e, 11)), rrotate(e, 25))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1529 local ch = bxor(band(e, f), band(bnot(e), g))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1530 local temp1 = (h + S1 + ch + K[j] + w[j])%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1531 local S0 = bxor(bxor(rrotate(a, 2), rrotate(a, 13)), rrotate(a, 22))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1532 local maj = bxor(bxor(band(a, b), band(a, c)), band(b, c))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1533 local temp2 = (S0 + maj)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1534 h, g, f, e, d, c, b, a = g, f, e, (d+temp1)%mod32, c, b, a, (temp1+temp2)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1535 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1536 C[1] = (C[1] + a)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1537 C[2] = (C[2] + b)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1538 C[3] = (C[3] + c)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1539 C[4] = (C[4] + d)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1540 C[5] = (C[5] + e)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1541 C[6] = (C[6] + f)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1542 C[7] = (C[7] + g)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1543 C[8] = (C[8] + h)%mod32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1544 return C\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1545 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1546\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1547 local function toBytes(t, n)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1548 local b = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1549 for i = 1, n do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1550 b[(i-1)*4+1] = band(brshift(t[i], 24), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1551 b[(i-1)*4+2] = band(brshift(t[i], 16), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1552 b[(i-1)*4+3] = band(brshift(t[i], 8), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1553 b[(i-1)*4+4] = band(t[i], 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1554 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1555 return setmetatable(b, byteTableMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1556 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1557\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1558 local function digest(data)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1559 data = data or \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1560 data = type(data) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and {upack(data)} or {tostring(data):byte(1,-1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1561\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1562 data = preprocess(data)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1563 local C = {upack(H)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1564 for i = 1, #data do C = digestblock(data[i], C) end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1565 return toBytes(C, 8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1566 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1567\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1568 local function hmac(data, key)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1569 local data = type(data) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and {upack(data)} or {tostring(data):byte(1,-1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1570 local key = type(key) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and {upack(key)} or {tostring(key):byte(1,-1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1571\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1572 local blocksize = 64\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1573\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1574 key = #key > blocksize and digest(key) or key\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1575\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1576 local ipad = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1577 local opad = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1578 local padded_key = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1579\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1580 for i = 1, blocksize do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1581 ipad[i] = bxor(0x36, key[i] or 0)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1582 opad[i] = bxor(0x5C, key[i] or 0)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1583 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1584\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1585 for i = 1, #data do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1586 ipad[blocksize+i] = data[i]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1587 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1588\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1589 ipad = digest(ipad)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1590\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1591 for i = 1, blocksize do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1592 padded_key[i] = opad[i]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1593 padded_key[blocksize+i] = ipad[i]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1594 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1595\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1596 return digest(padded_key)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1597 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1598\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1599 local function pbkdf2(pass, salt, iter, dklen)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1600 local salt = type(salt) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and salt or {tostring(salt):byte(1,-1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1601 local hashlen = 32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1602 local dklen = dklen or 32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1603 local block = 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1604 local out = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1605\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1606 while dklen > 0 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1607 local ikey = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1608 local isalt = {upack(salt)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1609 local clen = dklen > hashlen and hashlen or dklen\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1610\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1611 isalt[#isalt+1] = band(brshift(block, 24), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1612 isalt[#isalt+1] = band(brshift(block, 16), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1613 isalt[#isalt+1] = band(brshift(block, 8), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1614 isalt[#isalt+1] = band(block, 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1615\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1616 for j = 1, iter do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1617 isalt = hmac(isalt, pass)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1618 for k = 1, clen do ikey[k] = bxor(isalt[k], ikey[k] or 0) end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1619 if j % 200 == 0 then os.queueEvent(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"PBKDF2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", j) coroutine.yield(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"PBKDF2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\") end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1620 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1621 dklen = dklen - clen\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1622 block = block+1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1623 for k = 1, clen do out[#out+1] = ikey[k] end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1624 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1625\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1626 return setmetatable(out, byteTableMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1627 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1628\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1629 return {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1630 digest = digest,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1631 hmac = hmac,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1632 pbkdf2 = pbkdf2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1633 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1634end)()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1635\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1636-- Chacha20 cipher in ComputerCraft\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1637-- By Anavrins\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1638-- For help and details, you can PM me on the CC forums\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1639-- You may use this code in your projects without asking me, as long as credit is given and this header is kept intact\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1640-- http://www.computercraft.info/forums2/index.php?/user/12870-anavrins\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1641-- http://pastebin.com/GPzf9JSa\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1642-- Last update: April 17, 2017\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1643local chacha20 = (function()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1644 local bxor = bit32.bxor\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1645 local band = bit32.band\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1646 local blshift = bit32.lshift\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1647 local brshift = bit32.arshift\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1648\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1649 local mod = 2^32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1650 local tau = {(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"expand 16-byte k\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"):byte(1,-1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1651 local sigma = {(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"expand 32-byte k\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"):byte(1,-1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1652\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1653 local function rotl(n, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1654 local s = n/(2^(32-b))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1655 local f = s%1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1656 return (s-f) + f*mod\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1657 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1658\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1659 local function quarterRound(s, a, b, c, d)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1660 s[a] = (s[a]+s[b])%mod; s[d] = rotl(bxor(s[d], s[a]), 16)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1661 s[c] = (s[c]+s[d])%mod; s[b] = rotl(bxor(s[b], s[c]), 12)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1662 s[a] = (s[a]+s[b])%mod; s[d] = rotl(bxor(s[d], s[a]), 8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1663 s[c] = (s[c]+s[d])%mod; s[b] = rotl(bxor(s[b], s[c]), 7)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1664 return s\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1665 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1666\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1667 local function hashBlock(state, rnd)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1668 local s = {unpack(state)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1669 for i = 1, rnd do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1670 local r = i%2==1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1671 s = r and quarterRound(s, 1, 5, 9, 13) or quarterRound(s, 1, 6, 11, 16)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1672 s = r and quarterRound(s, 2, 6, 10, 14) or quarterRound(s, 2, 7, 12, 13)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1673 s = r and quarterRound(s, 3, 7, 11, 15) or quarterRound(s, 3, 8, 9, 14)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1674 s = r and quarterRound(s, 4, 8, 12, 16) or quarterRound(s, 4, 5, 10, 15)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1675 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1676 for i = 1, 16 do s[i] = (s[i]+state[i])%mod end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1677 return s\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1678 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1679\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1680 local function LE_toInt(bs, i)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1681 return (bs[i+1] or 0)+\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1682 blshift((bs[i+2] or 0), 8)+\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1683 blshift((bs[i+3] or 0), 16)+\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1684 blshift((bs[i+4] or 0), 24)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1685 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1686\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1687 local function initState(key, nonce, counter)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1688 local isKey256 = #key == 32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1689 local const = isKey256 and sigma or tau\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1690 local state = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1691\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1692 state[ 1] = LE_toInt(const, 0)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1693 state[ 2] = LE_toInt(const, 4)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1694 state[ 3] = LE_toInt(const, 8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1695 state[ 4] = LE_toInt(const, 12)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1696\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1697 state[ 5] = LE_toInt(key, 0)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1698 state[ 6] = LE_toInt(key, 4)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1699 state[ 7] = LE_toInt(key, 8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1700 state[ 8] = LE_toInt(key, 12)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1701 state[ 9] = LE_toInt(key, isKey256 and 16 or 0)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1702 state[10] = LE_toInt(key, isKey256 and 20 or 4)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1703 state[11] = LE_toInt(key, isKey256 and 24 or 8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1704 state[12] = LE_toInt(key, isKey256 and 28 or 12)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1705\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1706 state[13] = counter\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1707 state[14] = LE_toInt(nonce, 0)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1708 state[15] = LE_toInt(nonce, 4)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1709 state[16] = LE_toInt(nonce, 8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1710\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1711 return state\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1712 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1713\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1714 local function serialize(state)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1715 local r = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1716 for i = 1, 16 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1717 r[#r+1] = band(state[i], 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1718 r[#r+1] = band(brshift(state[i], 8), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1719 r[#r+1] = band(brshift(state[i], 16), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1720 r[#r+1] = band(brshift(state[i], 24), 0xFF)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1721 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1722 return r\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1723 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1724\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1725 function crypt(data, key, nonce, cntr, round)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1726 assert(type(key) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"ChaCha20: Invalid key format (\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"..type(key)..\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"), must be table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1727 assert(type(nonce) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"ChaCha20: Invalid nonce format (\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"..type(nonce)..\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"), must be table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1728 assert(#key == 16 or #key == 32, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"ChaCha20: Invalid key length (\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"..#key..\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"), must be 16 or 32\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1729 assert(#nonce == 12, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"ChaCha20: Invalid nonce length (\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"..#nonce..\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"), must be 12\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1730\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1731 local data = type(data) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and {unpack(data)} or {tostring(data):byte(1,-1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1732 cntr = tonumber(cntr) or 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1733 round = tonumber(round) or 20\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1734\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1735 local out = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1736 local state = initState(key, nonce, cntr)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1737 local blockAmt = math.floor(#data/64)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1738 for i = 0, blockAmt do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1739 local ks = serialize(hashBlock(state, round))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1740 state[13] = (state[13]+1) % mod\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1741\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1742 local block = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1743 for j = 1, 64 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1744 block[j] = data[((i)*64)+j]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1745 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1746 for j = 1, #block do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1747 out[#out+1] = bxor(block[j], ks[j])\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1748 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1749\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1750 if i % 1000 == 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1751 os.queueEvent(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1752 os.pullEvent(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1753 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1754 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1755 return setmetatable(out, byteTableMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1756 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1757\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1758 return {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1759 crypt = crypt\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1760 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1761end)()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1762\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1763-- random.lua - Random Byte Generator\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1764local random = (function()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1765 local oldPull = os.pullEvent\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1766 local entropy = \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1767 local accumulator = \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1768 local entropyPath = \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"/.random\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1769 local running = false\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1770\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1771 local function feed(data)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1772 accumulator = accumulator .. (data or \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1773 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1774\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1775 local function digest()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1776 local input = accumulator:sub(1, 87)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1777 accumulator = accumulator:sub(88)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1778\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1779 entropy = tostring(sha256.digest(entropy .. input))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1780 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1781\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1782 if fs.exists(entropyPath) then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1783 local entropyFile = fs.open(entropyPath, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"rb\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1784 feed(entropyFile.readAll())\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1785 entropyFile.close()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1786 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1787\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1788 feed(tostring(math.random(1, 2^31 - 1)))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1789 feed(tostring(math.random(1, 2^31 - 1)))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1790 for i = 1, 10000 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1791 feed(tostring(os.epoch(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"utc\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")):sub(-8))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1792 feed(tostring({}):sub(-8))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1793 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1794 digest()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1795\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1796 local function save()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1797 feed(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"save\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1798 feed(tostring(os.epoch(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"utc\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")):sub(-8))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1799 feed(tostring({}):sub(-8))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1800 digest()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1801\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1802 local entropyFile = fs.open(entropyPath, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"wb\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1803 entropyFile.write(tostring(sha256.hmac(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"save\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", entropy)))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1804 entropy = tostring(sha256.digest(entropy))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1805 entropyFile.close()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1806 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1807 save()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1808\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1809 local function seed(data)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1810 feed(data)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1811 feed(tostring(os.epoch(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"utc\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1812 feed(tostring({}))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1813 digest()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1814 save()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1815 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1816\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1817 local function random()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1818 feed(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"random\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1819 feed(tostring(os.epoch(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"utc\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")):sub(-8))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1820 feed(tostring({}):sub(-8))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1821 digest()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1822 save()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1823\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1824 local result = sha256.hmac(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"out\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", entropy)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1825 entropy = tostring(sha256.digest(entropy))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1826 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1827 return result\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1828 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1829\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1830 return {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1831 seed = seed,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1832 save = save,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1833 random = random\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1834 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1835end)()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1836\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1837-- Big integer arithmetic for 168-bit (and 336-bit) numbers\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1838-- Numbers are represented as little-endian tables of 24-bit integers\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1839local arith = (function()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1840 local function isEqual(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1841 return (\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1842 a[1] == b[1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1843 and a[2] == b[2]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1844 and a[3] == b[3]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1845 and a[4] == b[4]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1846 and a[5] == b[5]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1847 and a[6] == b[6]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1848 and a[7] == b[7]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1849 )\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1850 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1851\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1852 local function compare(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1853 for i = 7, 1, -1 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1854 if a[i] > b[i] then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1855 return 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1856 elseif a[i] < b[i] then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1857 return -1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1858 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1859 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1860\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1861 return 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1862 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1863\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1864 local function add(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1865 -- c7 may be greater than 2^24 before reduction\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1866 local c1 = a[1] + b[1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1867 local c2 = a[2] + b[2]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1868 local c3 = a[3] + b[3]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1869 local c4 = a[4] + b[4]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1870 local c5 = a[5] + b[5]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1871 local c6 = a[6] + b[6]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1872 local c7 = a[7] + b[7]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1873\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1874 if c1 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1875 c2 = c2 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1876 c1 = c1 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1877 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1878 if c2 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1879 c3 = c3 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1880 c2 = c2 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1881 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1882 if c3 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1883 c4 = c4 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1884 c3 = c3 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1885 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1886 if c4 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1887 c5 = c5 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1888 c4 = c4 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1889 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1890 if c5 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1891 c6 = c6 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1892 c5 = c5 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1893 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1894 if c6 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1895 c7 = c7 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1896 c6 = c6 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1897 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1898 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1899 return {c1, c2, c3, c4, c5, c6, c7}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1900 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1901\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1902 local function sub(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1903 -- c7 may be negative before reduction\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1904 local c1 = a[1] - b[1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1905 local c2 = a[2] - b[2]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1906 local c3 = a[3] - b[3]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1907 local c4 = a[4] - b[4]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1908 local c5 = a[5] - b[5]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1909 local c6 = a[6] - b[6]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1910 local c7 = a[7] - b[7]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1911\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1912 if c1 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1913 c2 = c2 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1914 c1 = c1 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1915 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1916 if c2 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1917 c3 = c3 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1918 c2 = c2 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1919 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1920 if c3 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1921 c4 = c4 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1922 c3 = c3 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1923 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1924 if c4 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1925 c5 = c5 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1926 c4 = c4 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1927 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1928 if c5 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1929 c6 = c6 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1930 c5 = c5 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1931 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1932 if c6 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1933 c7 = c7 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1934 c6 = c6 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1935 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1936 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1937 return {c1, c2, c3, c4, c5, c6, c7}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1938 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1939\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1940 local function rShift(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1941 local c1 = a[1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1942 local c2 = a[2]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1943 local c3 = a[3]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1944 local c4 = a[4]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1945 local c5 = a[5]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1946 local c6 = a[6]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1947 local c7 = a[7]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1948\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1949 c1 = c1 / 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1950 c1 = c1 - c1 % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1951 c1 = c1 + (c2 % 2) * 0x800000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1952 c2 = c2 / 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1953 c2 = c2 - c2 % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1954 c2 = c2 + (c3 % 2) * 0x800000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1955 c3 = c3 / 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1956 c3 = c3 - c3 % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1957 c3 = c3 + (c4 % 2) * 0x800000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1958 c4 = c4 / 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1959 c4 = c4 - c4 % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1960 c4 = c4 + (c5 % 2) * 0x800000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1961 c5 = c5 / 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1962 c5 = c5 - c5 % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1963 c5 = c5 + (c6 % 2) * 0x800000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1964 c6 = c6 / 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1965 c6 = c6 - c6 % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1966 c6 = c6 + (c7 % 2) * 0x800000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1967 c7 = c7 / 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1968 c7 = c7 - c7 % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1969\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1970 return {c1, c2, c3, c4, c5, c6, c7}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1971 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1972\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1973 local function addDouble(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1974 -- a and b are 336-bit integers (14 words)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1975 local c1 = a[1] + b[1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1976 local c2 = a[2] + b[2]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1977 local c3 = a[3] + b[3]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1978 local c4 = a[4] + b[4]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1979 local c5 = a[5] + b[5]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1980 local c6 = a[6] + b[6]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1981 local c7 = a[7] + b[7]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1982 local c8 = a[8] + b[8]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1983 local c9 = a[9] + b[9]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1984 local c10 = a[10] + b[10]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1985 local c11 = a[11] + b[11]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1986 local c12 = a[12] + b[12]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1987 local c13 = a[13] + b[13]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1988 local c14 = a[14] + b[14]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1989\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1990 if c1 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1991 c2 = c2 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1992 c1 = c1 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1993 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1994 if c2 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1995 c3 = c3 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1996 c2 = c2 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1997 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1998 if c3 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
1999 c4 = c4 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2000 c3 = c3 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2001 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2002 if c4 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2003 c5 = c5 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2004 c4 = c4 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2005 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2006 if c5 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2007 c6 = c6 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2008 c5 = c5 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2009 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2010 if c6 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2011 c7 = c7 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2012 c6 = c6 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2013 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2014 if c7 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2015 c8 = c8 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2016 c7 = c7 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2017 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2018 if c8 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2019 c9 = c9 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2020 c8 = c8 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2021 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2022 if c9 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2023 c10 = c10 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2024 c9 = c9 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2025 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2026 if c10 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2027 c11 = c11 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2028 c10 = c10 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2029 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2030 if c11 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2031 c12 = c12 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2032 c11 = c11 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2033 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2034 if c12 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2035 c13 = c13 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2036 c12 = c12 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2037 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2038 if c13 > 0xffffff then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2039 c14 = c14 + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2040 c13 = c13 - 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2041 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2042\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2043 return {c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2044 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2045\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2046 local function mult(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2047 local a1, a2, a3, a4, a5, a6, a7 = unpack(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2048 local b1, b2, b3, b4, b5, b6, b7 = unpack(b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2049 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2050 local c1 = a1 * b1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2051 local c2 = a1 * b2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2052 c2 = c2 + a2 * b1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2053 local c3 = a1 * b3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2054 c3 = c3 + a2 * b2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2055 c3 = c3 + a3 * b1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2056 local c4 = a1 * b4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2057 c4 = c4 + a2 * b3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2058 c4 = c4 + a3 * b2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2059 c4 = c4 + a4 * b1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2060 local c5 = a1 * b5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2061 c5 = c5 + a2 * b4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2062 c5 = c5 + a3 * b3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2063 c5 = c5 + a4 * b2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2064 c5 = c5 + a5 * b1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2065 local c6 = a1 * b6\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2066 c6 = c6 + a2 * b5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2067 c6 = c6 + a3 * b4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2068 c6 = c6 + a4 * b3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2069 c6 = c6 + a5 * b2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2070 c6 = c6 + a6 * b1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2071 local c7 = a1 * b7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2072 c7 = c7 + a2 * b6\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2073 c7 = c7 + a3 * b5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2074 c7 = c7 + a4 * b4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2075 c7 = c7 + a5 * b3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2076 c7 = c7 + a6 * b2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2077 c7 = c7 + a7 * b1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2078 local c8 = a2 * b7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2079 c8 = c8 + a3 * b6\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2080 c8 = c8 + a4 * b5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2081 c8 = c8 + a5 * b4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2082 c8 = c8 + a6 * b3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2083 c8 = c8 + a7 * b2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2084 local c9 = a3 * b7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2085 c9 = c9 + a4 * b6\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2086 c9 = c9 + a5 * b5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2087 c9 = c9 + a6 * b4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2088 c9 = c9 + a7 * b3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2089 local c10 = a4 * b7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2090 c10 = c10 + a5 * b6\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2091 c10 = c10 + a6 * b5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2092 c10 = c10 + a7 * b4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2093 local c11 = a5 * b7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2094 c11 = c11 + a6 * b6\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2095 c11 = c11 + a7 * b5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2096 local c12 = a6 * b7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2097 c12 = c12 + a7 * b6\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2098 local c13 = a7 * b7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2099 local c14 = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2100\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2101 local temp\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2102 temp = c1 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2103 c2 = c2 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2104 c1 = c1 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2105 temp = c2 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2106 c3 = c3 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2107 c2 = c2 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2108 temp = c3 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2109 c4 = c4 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2110 c3 = c3 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2111 temp = c4 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2112 c5 = c5 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2113 c4 = c4 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2114 temp = c5 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2115 c6 = c6 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2116 c5 = c5 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2117 temp = c6 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2118 c7 = c7 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2119 c6 = c6 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2120 temp = c7 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2121 c8 = c8 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2122 c7 = c7 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2123 temp = c8 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2124 c9 = c9 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2125 c8 = c8 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2126 temp = c9 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2127 c10 = c10 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2128 c9 = c9 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2129 temp = c10 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2130 c11 = c11 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2131 c10 = c10 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2132 temp = c11 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2133 c12 = c12 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2134 c11 = c11 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2135 temp = c12 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2136 c13 = c13 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2137 c12 = c12 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2138 temp = c13 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2139 c14 = c14 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2140 c13 = c13 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2141\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2142 return {c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2143 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2144\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2145 local function square(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2146 -- returns a 336-bit integer (14 words)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2147 local a1, a2, a3, a4, a5, a6, a7 = unpack(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2148 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2149 local c1 = a1 * a1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2150 local c2 = a1 * a2 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2151 local c3 = a1 * a3 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2152 c3 = c3 + a2 * a2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2153 local c4 = a1 * a4 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2154 c4 = c4 + a2 * a3 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2155 local c5 = a1 * a5 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2156 c5 = c5 + a2 * a4 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2157 c5 = c5 + a3 * a3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2158 local c6 = a1 * a6 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2159 c6 = c6 + a2 * a5 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2160 c6 = c6 + a3 * a4 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2161 local c7 = a1 * a7 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2162 c7 = c7 + a2 * a6 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2163 c7 = c7 + a3 * a5 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2164 c7 = c7 + a4 * a4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2165 local c8 = a2 * a7 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2166 c8 = c8 + a3 * a6 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2167 c8 = c8 + a4 * a5 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2168 local c9 = a3 * a7 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2169 c9 = c9 + a4 * a6 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2170 c9 = c9 + a5 * a5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2171 local c10 = a4 * a7 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2172 c10 = c10 + a5 * a6 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2173 local c11 = a5 * a7 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2174 c11 = c11 + a6 * a6\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2175 local c12 = a6 * a7 * 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2176 local c13 = a7 * a7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2177 local c14 = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2178\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2179 local temp\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2180 temp = c1 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2181 c2 = c2 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2182 c1 = c1 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2183 temp = c2 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2184 c3 = c3 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2185 c2 = c2 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2186 temp = c3 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2187 c4 = c4 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2188 c3 = c3 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2189 temp = c4 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2190 c5 = c5 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2191 c4 = c4 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2192 temp = c5 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2193 c6 = c6 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2194 c5 = c5 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2195 temp = c6 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2196 c7 = c7 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2197 c6 = c6 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2198 temp = c7 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2199 c8 = c8 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2200 c7 = c7 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2201 temp = c8 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2202 c9 = c9 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2203 c8 = c8 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2204 temp = c9 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2205 c10 = c10 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2206 c9 = c9 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2207 temp = c10 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2208 c11 = c11 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2209 c10 = c10 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2210 temp = c11 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2211 c12 = c12 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2212 c11 = c11 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2213 temp = c12 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2214 c13 = c13 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2215 c12 = c12 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2216 temp = c13 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2217 c14 = c14 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2218 c13 = c13 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2219\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2220 return {c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2221 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2222\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2223 -- Converts a number from base 2^startLength to base 2^resultLength\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2224 local function reword(start, startLength, resultLength)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2225 local result = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2226 local buffer = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2227 local bufferLength = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2228 local startIndex = 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2229 local totalBits = #start * startLength\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2230\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2231 while totalBits > 0 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2232 while bufferLength < resultLength do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2233 buffer = buffer + (start[startIndex] or 0) * 2^bufferLength\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2234 startIndex = startIndex + 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2235 bufferLength = bufferLength + startLength\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2236 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2237 result[#result + 1] = buffer % 2^resultLength\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2238 buffer = buffer / 2^resultLength\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2239 buffer = buffer - buffer % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2240 bufferLength = bufferLength - resultLength\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2241 totalBits = totalBits - resultLength\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2242 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2243\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2244 return result\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2245 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2246\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2247 local function mods(d, w)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2248 local result = d[1] % 2^w\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2249\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2250 if result >= 2^(w - 1) then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2251 result = result - 2^w\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2252 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2253\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2254 return result\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2255 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2256\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2257 -- Represents a 168-bit number as the (2^w)-ary Non-Adjacent Form\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2258 local function NAF(d, w)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2259 local t = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2260 local d = {unpack(d)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2261\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2262 for i = 1, 168 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2263 if d[1] % 2 == 1 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2264 t[#t + 1] = mods(d, w)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2265 d = sub(d, {t[#t], 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2266 else\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2267 t[#t + 1] = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2268 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2269\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2270 d = rShift(d)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2271 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2272\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2273 return t\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2274 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2275\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2276 return {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2277 isEqual = isEqual,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2278 compare = compare,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2279 add = add,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2280 sub = sub,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2281 addDouble = addDouble,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2282 mult = mult,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2283 square = square,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2284 reword = reword,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2285 NAF = NAF\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2286 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2287end)()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2288\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2289-- Arithmetic on the finite field of integers modulo p\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2290-- Where p is the finite field modulus\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2291local modp = (function()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2292 local add = arith.add\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2293 local sub = arith.sub\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2294 local addDouble = arith.addDouble\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2295 local mult = arith.mult\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2296 local square = arith.square\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2297\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2298 local p = {3, 0, 0, 0, 0, 0, 15761408}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2299\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2300 -- We're using the Montgomery Reduction for fast modular multiplication.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2301 -- https://en.wikipedia.org/wiki/Montgomery_modular_multiplication \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2302 -- r = 2^168\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2303 -- p * pInverse = -1 (mod r)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2304 -- r2 = r * r (mod p)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2305 local pInverse = {5592405, 5592405, 5592405, 5592405, 5592405, 5592405, 14800213}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2306 local r2 = {13533400, 837116, 6278376, 13533388, 837116, 6278376, 7504076}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2307\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2308 local function multByP(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2309 local a1, a2, a3, a4, a5, a6, a7 = unpack(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2310\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2311 local c1 = a1 * 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2312 local c2 = a2 * 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2313 local c3 = a3 * 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2314 local c4 = a4 * 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2315 local c5 = a5 * 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2316 local c6 = a6 * 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2317 local c7 = a1 * 15761408\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2318 c7 = c7 + a7 * 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2319 local c8 = a2 * 15761408\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2320 local c9 = a3 * 15761408\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2321 local c10 = a4 * 15761408\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2322 local c11 = a5 * 15761408\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2323 local c12 = a6 * 15761408\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2324 local c13 = a7 * 15761408\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2325 local c14 = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2326\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2327 local temp\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2328 temp = c1 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2329 c2 = c2 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2330 c1 = c1 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2331 temp = c2 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2332 c3 = c3 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2333 c2 = c2 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2334 temp = c3 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2335 c4 = c4 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2336 c3 = c3 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2337 temp = c4 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2338 c5 = c5 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2339 c4 = c4 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2340 temp = c5 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2341 c6 = c6 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2342 c5 = c5 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2343 temp = c6 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2344 c7 = c7 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2345 c6 = c6 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2346 temp = c7 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2347 c8 = c8 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2348 c7 = c7 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2349 temp = c8 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2350 c9 = c9 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2351 c8 = c8 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2352 temp = c9 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2353 c10 = c10 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2354 c9 = c9 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2355 temp = c10 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2356 c11 = c11 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2357 c10 = c10 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2358 temp = c11 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2359 c12 = c12 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2360 c11 = c11 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2361 temp = c12 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2362 c13 = c13 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2363 c12 = c12 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2364 temp = c13 / 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2365 c14 = c14 + (temp - temp % 1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2366 c13 = c13 % 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2367\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2368 return {c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2369 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2370\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2371 -- Reduces a number from [0, 2p - 1] to [0, p - 1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2372 local function reduceModP(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2373 -- a < p\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2374 if a[7] < 15761408 or a[7] == 15761408 and a[1] < 3 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2375 return {unpack(a)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2376 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2377\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2378 -- a > p\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2379 local c1 = a[1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2380 local c2 = a[2]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2381 local c3 = a[3]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2382 local c4 = a[4]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2383 local c5 = a[5]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2384 local c6 = a[6]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2385 local c7 = a[7]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2386\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2387 c1 = c1 - 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2388 c7 = c7 - 15761408\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2389\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2390 if c1 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2391 c2 = c2 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2392 c1 = c1 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2393 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2394 if c2 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2395 c3 = c3 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2396 c2 = c2 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2397 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2398 if c3 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2399 c4 = c4 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2400 c3 = c3 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2401 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2402 if c4 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2403 c5 = c5 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2404 c4 = c4 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2405 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2406 if c5 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2407 c6 = c6 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2408 c5 = c5 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2409 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2410 if c6 < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2411 c7 = c7 - 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2412 c6 = c6 + 0x1000000\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2413 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2414\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2415 return {c1, c2, c3, c4, c5, c6, c7}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2416 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2417\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2418 local function addModP(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2419 return reduceModP(add(a, b))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2420 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2421\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2422 local function subModP(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2423 local result = sub(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2424\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2425 if result[7] < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2426 result = add(result, p)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2427 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2428 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2429 return result\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2430 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2431\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2432 -- Montgomery REDC algorithn\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2433 -- Reduces a number from [0, p^2 - 1] to [0, p - 1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2434 local function REDC(T)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2435 local m = {unpack(mult({unpack(T, 1, 7)}, pInverse), 1, 7)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2436 local t = {unpack(addDouble(T, multByP(m)), 8, 14)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2437\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2438 return reduceModP(t)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2439 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2440\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2441 local function multModP(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2442 -- Only works with a, b in Montgomery form\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2443 return REDC(mult(a, b))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2444 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2445\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2446 local function squareModP(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2447 -- Only works with a in Montgomery form\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2448 return REDC(square(a))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2449 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2450\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2451 local function montgomeryModP(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2452 return multModP(a, r2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2453 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2454\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2455 local function inverseMontgomeryModP(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2456 local a = {unpack(a)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2457\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2458 for i = 8, 14 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2459 a[i] = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2460 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2461\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2462 return REDC(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2463 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2464\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2465 local ONE = montgomeryModP({1, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2466\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2467 local function expModP(base, exponentBinary)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2468 local base = {unpack(base)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2469 local result = {unpack(ONE)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2470\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2471 for i = 1, 168 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2472 if exponentBinary[i] == 1 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2473 result = multModP(result, base)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2474 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2475 base = squareModP(base)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2476 end \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2477\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2478 return result\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2479 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2480\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2481 return {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2482 addModP = addModP,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2483 subModP = subModP,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2484 multModP = multModP,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2485 squareModP = squareModP,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2486 montgomeryModP = montgomeryModP,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2487 inverseMontgomeryModP = inverseMontgomeryModP,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2488 expModP = expModP\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2489 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2490end)()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2491\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2492-- Arithmetic on the Finite Field of Integers modulo q\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2493-- Where q is the generator's subgroup order.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2494local modq = (function()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2495 local isEqual = arith.isEqual\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2496 local compare = arith.compare\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2497 local add = arith.add\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2498 local sub = arith.sub\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2499 local addDouble = arith.addDouble\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2500 local mult = arith.mult\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2501 local square = arith.square\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2502 local reword = arith.reword\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2503\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2504 local modQMT\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2505\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2506 local q = {9622359, 6699217, 13940450, 16775734, 16777215, 16777215, 3940351}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2507 local qMinusTwoBinary = {1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2508 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2509 -- We're using the Montgomery Reduction for fast modular multiplication.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2510 -- https://en.wikipedia.org/wiki/Montgomery_modular_multiplication \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2511 -- r = 2^168\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2512 -- q * qInverse = -1 (mod r)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2513 -- r2 = r * r (mod q)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2514 local qInverse = {15218585, 5740955, 3271338, 9903997, 9067368, 7173545, 6988392}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2515 local r2 = {1336213, 11071705, 9716828, 11083885, 9188643, 1494868, 3306114}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2516\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2517 -- Reduces a number from [0, 2q - 1] to [0, q - 1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2518 local function reduceModQ(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2519 local result = {unpack(a)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2520\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2521 if compare(result, q) >= 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2522 result = sub(result, q)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2523 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2524\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2525 return setmetatable(result, modQMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2526 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2527\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2528 local function addModQ(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2529 return reduceModQ(add(a, b))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2530 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2531\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2532 local function subModQ(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2533 local result = sub(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2534\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2535 if result[7] < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2536 result = add(result, q)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2537 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2538 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2539 return setmetatable(result, modQMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2540 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2541\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2542 -- Montgomery REDC algorithn\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2543 -- Reduces a number from [0, q^2 - 1] to [0, q - 1]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2544 local function REDC(T)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2545 local m = {unpack(mult({unpack(T, 1, 7)}, qInverse), 1, 7)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2546 local t = {unpack(addDouble(T, mult(m, q)), 8, 14)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2547\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2548 return reduceModQ(t)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2549 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2550\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2551 local function multModQ(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2552 -- Only works with a, b in Montgomery form\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2553 return REDC(mult(a, b))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2554 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2555\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2556 local function squareModQ(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2557 -- Only works with a in Montgomery form\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2558 return REDC(square(a))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2559 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2560\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2561 local function montgomeryModQ(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2562 return multModQ(a, r2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2563 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2564\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2565 local function inverseMontgomeryModQ(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2566 local a = {unpack(a)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2567\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2568 for i = 8, 14 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2569 a[i] = 0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2570 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2571\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2572 return REDC(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2573 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2574\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2575 local ONE = montgomeryModQ({1, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2576\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2577 local function expModQ(base, exponentBinary)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2578 local base = {unpack(base)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2579 local result = {unpack(ONE)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2580\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2581 for i = 1, 168 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2582 if exponentBinary[i] == 1 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2583 result = multModQ(result, base)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2584 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2585 base = squareModQ(base)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2586 end \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2587\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2588 return result\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2589 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2590\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2591 local function intExpModQ(base, exponent)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2592 local base = {unpack(base)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2593 local result = setmetatable({unpack(ONE)}, modQMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2594\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2595 if exponent < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2596 base = expModQ(base, qMinusTwoBinary)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2597 exponent = -exponent\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2598 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2599\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2600 while exponent > 0 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2601 if exponent % 2 == 1 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2602 result = multModQ(result, base)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2603 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2604 base = squareModQ(base)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2605 exponent = exponent / 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2606 exponent = exponent - exponent % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2607 end \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2608\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2609 return result\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2610 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2611\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2612 local function encodeModQ(a)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2613 local result = reword(a, 24, 8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2614\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2615 return setmetatable(result, byteTableMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2616 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2617\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2618 local function decodeModQ(s)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2619 s = type(s) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and {unpack(s, 1, 21)} or {tostring(s):byte(1, 21)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2620 local result = reword(s, 8, 24)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2621 result[8] = nil\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2622 result[7] = result[7] % q[7]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2623\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2624 return setmetatable(result, modQMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2625 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2626\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2627 local function hashModQ(data)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2628 local result = decodeModQ(sha256.digest(data))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2629\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2630 return setmetatable(result, modQMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2631 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2632\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2633 modQMT = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2634 __index = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2635 encode = function(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2636 return encodeModQ(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2637 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2638 },\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2639\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2640 __tostring = function(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2641 return self:encode():toHex()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2642 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2643\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2644 __add = function(self, other)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2645 if type(self) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2646 return other + self\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2647 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2648\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2649 if type(other) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2650 assert(other < 2^24, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number operand too big\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2651 other = montgomeryModQ({other, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2652 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2653\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2654 return addModQ(self, other)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2655 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2656\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2657 __sub = function(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2658 if type(a) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2659 assert(a < 2^24, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number operand too big\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2660 a = montgomeryModQ({a, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2661 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2662\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2663 if type(b) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2664 assert(b < 2^24, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number operand too big\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2665 b = montgomeryModQ({b, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2666 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2667\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2668 return subModQ(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2669 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2670\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2671 __unm = function(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2672 return subModQ(q, self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2673 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2674\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2675 __eq = function(self, other)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2676 return isEqual(self, other)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2677 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2678\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2679 __mul = function(self, other)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2680 if type(self) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2681 return other * self\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2682 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2683\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2684 -- EC point\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2685 -- Use the point's metatable to handle multiplication\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2686 if type(other) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and type(other[1]) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2687 return other * self\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2688 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2689\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2690 if type(other) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2691 assert(other < 2^24, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number operand too big\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2692 other = montgomeryModQ({other, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2693 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2694\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2695 return multModQ(self, other)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2696 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2697\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2698 __div = function(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2699 if type(a) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2700 assert(a < 2^24, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number operand too big\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2701 a = montgomeryModQ({a, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2702 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2703\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2704 if type(b) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2705 assert(b < 2^24, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number operand too big\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2706 b = montgomeryModQ({b, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2707 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2708\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2709 bInv = expModQ(b, qMinusTwoBinary)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2710\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2711 return multModQ(a, bInv)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2712 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2713\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2714 __pow = function(self, other)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2715 return intExpModQ(self, other)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2716 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2717 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2718\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2719 return {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2720 hashModQ = hashModQ,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2721 randomModQ = randomModQ,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2722 decodeModQ = decodeModQ,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2723 inverseMontgomeryModQ = inverseMontgomeryModQ\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2724 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2725end)()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2726\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2727-- Elliptic curve arithmetic\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2728local curve = (function()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2729 ---- About the Curve Itself\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2730 -- Field Size: 168 bits\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2731 -- Field Modulus (p): 481 * 2^159 + 3\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2732 -- Equation: x^2 + y^2 = 1 + 122 * x^2 * y^2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2733 -- Parameters: Edwards Curve with d = 122\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2734 -- Curve Order (n): 351491143778082151827986174289773107581916088585564\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2735 -- Cofactor (h): 4\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2736 -- Generator Order (q): 87872785944520537956996543572443276895479022146391\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2737 ---- About the Curve's Security\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2738 -- Current best attack security: 81.777 bits (Small Subgroup + Rho)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2739 -- Rho Security: log2(0.884 * sqrt(q)) = 82.777 bits\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2740 -- Transfer Security? Yes: p ~= q; k > 20\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2741 -- Field Discriminant Security? Yes:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2742 -- t = 27978492958645335688000168\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2743 -- s = 10\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2744 -- |D| = 6231685068753619775430107799412237267322159383147 > 2^100\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2745 -- Rigidity? No, not at all.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2746 -- XZ/YZ Ladder Security? No: Single coordinate ladders are insecure.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2747 -- Small Subgroup Security? No.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2748 -- Invalid Curve Security? Yes: Points are checked before every operation.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2749 -- Invalid Curve Twist Security? No: Don't use single coordinate ladders.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2750 -- Completeness? Yes: The curve is complete.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2751 -- Indistinguishability? Yes (Elligator 2), but not implemented.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2752\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2753 local isEqual = arith.isEqual\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2754 local NAF = arith.NAF\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2755 local reword = arith.reword\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2756 local multModP = modp.multModP\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2757 local squareModP = modp.squareModP\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2758 local addModP = modp.addModP\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2759 local subModP = modp.subModP\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2760 local montgomeryModP = modp.montgomeryModP\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2761 local inverseMontgomeryModP = modp.inverseMontgomeryModP\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2762 local expModP = modp.expModP\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2763 local inverseMontgomeryModQ = modq.inverseMontgomeryModQ\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2764 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2765 local pointMT\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2766 local ZERO = {0, 0, 0, 0, 0, 0, 0}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2767 local ONE = montgomeryModP({1, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2768\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2769 -- Curve Parameters\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2770 local d = montgomeryModP({122, 0, 0, 0, 0, 0, 0})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2771 local p = {3, 0, 0, 0, 0, 0, 15761408}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2772 local pMinusTwoBinary = {1, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2773 local pMinusThreeOverFourBinary = {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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2774 local G = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2775 {6636044, 10381432, 15741790, 2914241, 5785600, 264923, 4550291},\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2776 {13512827, 8449886, 5647959, 1135556, 5489843, 7177356, 8002203},\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2777 {unpack(ONE)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2778 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2779 local O = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2780 {unpack(ZERO)},\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2781 {unpack(ONE)},\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2782 {unpack(ONE)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2783 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2784\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2785 -- Projective Coordinates for Edwards curves for point addition/doubling.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2786 -- Points are represented as: (X:Y:Z) where x = X/Z and y = Y/Z\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2787 -- The identity element is represented by (0:1:1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2788 -- Point operation formulas are available on the EFD:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2789 -- https://www.hyperelliptic.org/EFD/g1p/auto-edwards-projective.html\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2790 local function pointDouble(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2791 -- 3M + 4S\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2792 local X1, Y1, Z1 = unpack(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2793\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2794 local b = addModP(X1, Y1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2795 local B = squareModP(b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2796 local C = squareModP(X1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2797 local D = squareModP(Y1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2798 local E = addModP(C, D)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2799 local H = squareModP(Z1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2800 local J = subModP(E, addModP(H, H))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2801 local X3 = multModP(subModP(B, E), J)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2802 local Y3 = multModP(E, subModP(C, D))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2803 local Z3 = multModP(E, J)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2804 local P3 = {X3, Y3, Z3}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2805\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2806 return setmetatable(P3, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2807 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2808\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2809 local function pointAdd(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2810 -- 10M + 1S\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2811 local X1, Y1, Z1 = unpack(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2812 local X2, Y2, Z2 = unpack(P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2813\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2814 local A = multModP(Z1, Z2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2815 local B = squareModP(A)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2816 local C = multModP(X1, X2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2817 local D = multModP(Y1, Y2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2818 local E = multModP(d, multModP(C, D))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2819 local F = subModP(B, E)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2820 local G = addModP(B, E)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2821 local X3 = multModP(A, multModP(F, subModP(multModP(addModP(X1, Y1), addModP(X2, Y2)), addModP(C, D))))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2822 local Y3 = multModP(A, multModP(G, subModP(D, C)))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2823 local Z3 = multModP(F, G)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2824 local P3 = {X3, Y3, Z3}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2825\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2826 return setmetatable(P3, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2827 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2828\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2829 local function pointNeg(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2830 local X1, Y1, Z1 = unpack(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2831\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2832 local X3 = subModP(ZERO, X1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2833 local Y3 = {unpack(Y1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2834 local Z3 = {unpack(Z1)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2835 local P3 = {X3, Y3, Z3}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2836\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2837 return setmetatable(P3, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2838 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2839\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2840 local function pointSub(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2841 return pointAdd(P1, pointNeg(P2))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2842 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2843\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2844 -- Converts (X:Y:Z) into (X:Y:1) = (x:y:1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2845 local function pointScale(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2846 local X1, Y1, Z1 = unpack(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2847\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2848 local A = expModP(Z1, pMinusTwoBinary)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2849 local X3 = multModP(X1, A)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2850 local Y3 = multModP(Y1, A)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2851 local Z3 = {unpack(ONE)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2852 local P3 = {X3, Y3, Z3}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2853\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2854 return setmetatable(P3, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2855 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2856\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2857 local function pointIsEqual(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2858 local X1, Y1, Z1 = unpack(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2859 local X2, Y2, Z2 = unpack(P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2860\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2861 local A1 = multModP(X1, Z2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2862 local B1 = multModP(Y1, Z2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2863 local A2 = multModP(X2, Z1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2864 local B2 = multModP(Y2, Z1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2865\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2866 return isEqual(A1, A2) and isEqual(B1, B2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2867 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2868\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2869 -- Checks if a projective point satisfies the curve equation\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2870 local function pointIsOnCurve(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2871 local X1, Y1, Z1 = unpack(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2872\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2873 local X12 = squareModP(X1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2874 local Y12 = squareModP(Y1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2875 local Z12 = squareModP(Z1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2876 local Z14 = squareModP(Z12)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2877 local a = addModP(X12, Y12)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2878 a = multModP(a, Z12)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2879 local b = multModP(d, multModP(X12, Y12))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2880 b = addModP(Z14, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2881\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2882 return isEqual(a, b)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2883 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2884\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2885 local function pointIsInf(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2886 return isEqual(P1[1], ZERO)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2887 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2888\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2889 -- W-ary Non-Adjacent Form (wNAF) method for scalar multiplication:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2890 -- https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#w-ary_non-adjacent_form_(wNAF)_method\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2891 local function scalarMult(multiplier, P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2892 -- w = 5\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2893 local naf = NAF(multiplier, 5)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2894 local PTable = {P1}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2895 local P2 = pointDouble(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2896 local Q = {{unpack(ZERO)}, {unpack(ONE)}, {unpack(ONE)}}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2897\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2898 for i = 3, 31, 2 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2899 PTable[i] = pointAdd(PTable[i - 2], P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2900 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2901\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2902 for i = #naf, 1, -1 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2903 Q = pointDouble(Q)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2904\\\\\\\\\\\\\\\\009\\\\\\\\\\\\\\\\009\\\\\\\\\\\\\\\\009local TMP = naf[i]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2905 if TMP > 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2906 Q = pointAdd(Q, PTable[TMP])\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2907 elseif TMP < 0 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2908 Q = pointSub(Q, PTable[-TMP])\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2909 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2910 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2911\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2912 return setmetatable(Q, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2913 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2914\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2915 -- Lookup table 4-ary NAF method for scalar multiplication by G.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2916 -- Precomputations for the regular NAF method are done before the multiplication.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2917 local GTable = {G}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2918 for i = 2, 168 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2919 GTable[i] = pointDouble(GTable[i - 1])\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2920 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2921\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2922 local function scalarMultG(multiplier)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2923 local naf = NAF(multiplier, 2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2924 local Q = {{unpack(ZERO)}, {unpack(ONE)}, {unpack(ONE)}}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2925\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2926 for i = 1, 168 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2927 if naf[i] == 1 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2928 Q = pointAdd(Q, GTable[i])\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2929 elseif naf[i] == -1 then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2930 Q = pointSub(Q, GTable[i])\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2931 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2932 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2933\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2934 return setmetatable(Q, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2935 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2936\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2937 -- Point compression and encoding.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2938 -- Compresses curve points to 22 bytes.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2939 local function pointEncode(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2940 P1 = pointScale(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2941 local result = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2942 local x, y = unpack(P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2943 local temp\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2944\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2945 -- Encode y\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2946 result = reword(y, 24, 8)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2947 -- Encode one bit from x\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2948 result[22] = x[1] % 2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2949\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2950 return setmetatable(result, byteTableMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2951 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2952\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2953 local function pointDecode(enc)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2954 enc = type(enc) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and {unpack(enc, 1, 22)} or {tostring(enc):byte(1, 22)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2955 --Find x's bit\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2956 local xbit = enc[22]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2957 -- Decode y\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2958 local y = reword(enc, 8, 24)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2959 y[8] = nil\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2960 y[7] = y[7] % p[7]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2961 -- Find {x, -x} using curve equation\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2962 local y2 = squareModP(y)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2963 local u = subModP(y2, ONE)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2964 local v = subModP(multModP(d, y2), ONE)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2965 local u2 = squareModP(u)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2966 local u3 = multModP(u, u2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2967 local u5 = multModP(u3, u2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2968 local v3 = multModP(v, squareModP(v))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2969 local w = multModP(u5, v3)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2970 local x = multModP(u3, multModP(v, expModP(w, pMinusThreeOverFourBinary)))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2971 -- Use x's bit to find x from {x, -x}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2972 if x[1] % 2 ~= xbit then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2973 x = subModP(ZERO, x)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2974 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2975 local P3 = {x, y, {unpack(ONE)}}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2976\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2977 return setmetatable(P3, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2978 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2979\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2980 pointMT = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2981 __index = {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2982 isOnCurve = function(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2983 return pointIsOnCurve(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2984 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2985\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2986 isInf = function(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2987 return self:isOnCurve() and pointIsInf(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2988 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2989\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2990 encode = function(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2991 return pointEncode(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2992 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2993 },\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2994\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2995 __tostring = function(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2996 return self:encode():toHex()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2997 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2998\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
2999 __add = function(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3000 assert(P1:isOnCurve(), \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"invalid point\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3001 assert(P2:isOnCurve(), \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"invalid point\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3002 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3003 return pointAdd(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3004 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3005\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3006 __sub = function(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3007 assert(P1:isOnCurve(), \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"invalid point\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3008 assert(P2:isOnCurve(), \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"invalid point\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3009 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3010 return pointSub(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3011 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3012\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3013 __unm = function(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3014 assert(self:isOnCurve(), \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"invalid point\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3015 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3016 return pointNeg(self)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3017 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3018\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3019 __eq = function(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3020 assert(P1:isOnCurve(), \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"invalid point\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3021 assert(P2:isOnCurve(), \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"invalid point\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3022 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3023 return pointIsEqual(P1, P2)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3024 end,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3025\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3026 __mul = function(P1, s)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3027 if type(P1) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3028 return s * P1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3029 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3030\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3031 if type(s) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3032 assert(s < 2^24, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"number multiplier too big\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3033 s = {s, 0, 0, 0, 0, 0, 0}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3034 else\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3035 s = inverseMontgomeryModQ(s)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3036 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3037\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3038 if P1 == G then\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3039 return scalarMultG(s)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3040 else\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3041 return scalarMult(s, P1)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3042 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3043 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3044 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3045\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3046 G = setmetatable(G, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3047 O = setmetatable(O, pointMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3048\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3049 return {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3050 G = G,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3051 O = O,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3052 pointDecode = pointDecode\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3053 }\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3054end)()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3055\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3056local function getNonceFromEpoch()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3057 local nonce = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3058 local epoch = os.epoch(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"utc\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3059 for i = 1, 12 do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3060 nonce[#nonce + 1] = epoch % 256\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3061 epoch = epoch / 256\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3062 epoch = epoch - epoch % 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3063 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3064\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3065 return nonce\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3066end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3067\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3068local function encrypt(data, key)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3069 local encKey = sha256.hmac(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"encKey\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", key)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3070 local macKey = sha256.hmac(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"macKey\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", key)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3071 local nonce = getNonceFromEpoch()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3072 local ciphertext = chacha20.crypt(data, encKey, nonce)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3073 local result = nonce\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3074 for i = 1, #ciphertext do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3075 result[#result + 1] = ciphertext[i]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3076 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3077 local mac = sha256.hmac(result, macKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3078 for i = 1, #mac do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3079 result[#result + 1] = mac[i]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3080 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3081\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3082 return setmetatable(result, byteTableMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3083end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3084\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3085local function decrypt(data, key)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3086 local encKey = sha256.hmac(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"encKey\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", key)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3087 local macKey = sha256.hmac(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"macKey\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", key)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3088 local mac = sha256.hmac({unpack(data, 1, #data - 32)}, macKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3089 local messageMac = {unpack(data, #data - 31)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3090 assert(mac:isEqual(messageMac), \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"invalid mac\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3091 local nonce = {unpack(data, 1, 12)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3092 local ciphertext = {unpack(data, 13, #data - 32)}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3093 local result = chacha20.crypt(ciphertext, encKey, nonce)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3094\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3095 return setmetatable(result, byteTableMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3096end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3097\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3098local function keypair(seed)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3099 seed = seed or random.random()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3100 local x = modq.hashModQ(seed)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3101 local Y = curve.G * x\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3102\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3103 local privateKey = x:encode()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3104 local publicKey = Y:encode()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3105\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3106 return privateKey, publicKey\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3107end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3108\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3109local function exchange(privateKey, publicKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3110 local x = modq.decodeModQ(privateKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3111 local Y = curve.pointDecode(publicKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3112\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3113 local Z = Y * x\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3114\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3115 local sharedSecret = sha256.digest(Z:encode())\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3116\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3117 return sharedSecret\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3118end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3119\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3120local function sign(privateKey, message)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3121 local message = type(message) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and string.char(unpack(message)) or tostring(message)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3122 local privateKey = type(privateKey) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and string.char(unpack(privateKey)) or tostring(privateKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3123 local x = modq.decodeModQ(privateKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3124 local k = modq.hashModQ(message .. privateKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3125 local R = curve.G * k\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3126 local e = modq.hashModQ(message .. tostring(R))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3127 local s = k - x * e\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3128\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3129 e = e:encode()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3130 s = s:encode()\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3131\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3132 local result = e\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3133 for i = 1, #s do\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3134 result[#result + 1] = s[i]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3135 end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3136\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3137 return setmetatable(result, byteTableMT)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3138end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3139\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3140local function verify(publicKey, message, signature)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3141 local message = type(message) == \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"table\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" and string.char(unpack(message)) or tostring(message)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3142 Y = curve.pointDecode(publicKey)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3143 e = modq.decodeModQ({unpack(signature, 1, #signature / 2)})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3144 s = modq.decodeModQ({unpack(signature, #signature / 2 + 1)})\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3145 Rv = curve.G * s + Y * e\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3146 ev = modq.hashModQ(message .. tostring(Rv))\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3147\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3148 return ev == e\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3149end\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3150\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3151local API = {}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3152API.ChaCha20 = chacha20\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3153API.SHA256 = sha256\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3154API.random = random\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3155API.encrypt = encrypt\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3156API.decrypt = decrypt\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3157API.keypair = keypair\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3158API.exchange = exchange\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3159API.sign = sign\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3160API.verify = verify\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3161\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3162__declare(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"crypt\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", API)\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3163\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3164return 1\\\\\\\\\\\\\\\"\\\\\\\",\\\\\\\
3165}\\\",\\\
3166 \\\"F:esiboot.b\\\",\\\
3167 \\\"\\\\\\\"local sr = shell.run\\\\\\\\\\\\\\\
3168local args = {...}\\\\\\\\\\\\\\\
3169local bootConfigDefaults = {}\\\\\\\\\\\\\\\
3170bootConfigDefaults.script = \\\\\\\\\\\\\\\"Orbital\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\
3171\\\\\\\\\\\\\\\
3172local function boot_handleBootElement(str)\\\\\\\\\\\\\\\
3173 local s1 = \\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\
3174 local n1 = s1:len()\\\\\\\\\\\\\\\
3175 local n2 = str:len()\\\\\\\\\\\\\\\
3176 local s2 = string.sub(s1, 1, n1-n2)\\\\\\\\\\\\\\\
3177 return \\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"..str..s2..\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\
3178end\\\\\\\\\\\\\\\
3179\\\\\\\\\\\\\\\
3180local function boot_mprint(array, this, x, y, h, g)\\\\\\\\\\\\\\\
3181 local c1 = term.getBackgroundColor()\\\\\\\\\\\\\\\
3182 local c2 = term.getTextColor()\\\\\\\\\\\\\\\
3183 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3184 for i = 1, #array do\\\\\\\\\\\\\\\
3185 term.setCursorPos(x, y)\\\\\\\\\\\\\\\
3186 --Check if option selected\\\\\\\\\\\\\\\
3187 if i == this then \\\\\\\\\\\\\\\
3188 --Option selected \\\\\\\\\\\\\\\
3189 term.setBackgroundColor(h)\\\\\\\\\\\\\\\
3190 term.setTextColor(g)\\\\\\\\\\\\\\\
3191 else \\\\\\\\\\\\\\\
3192 --Option NOT selected \\\\\\\\\\\\\\\
3193 term.setBackgroundColor(g)\\\\\\\\\\\\\\\
3194 term.setTextColor(h)\\\\\\\\\\\\\\\
3195 end\\\\\\\\\\\\\\\
3196 --Print the string\\\\\\\\\\\\\\\
3197 term.write(boot_handleBootElement(array[i]))\\\\\\\\\\\\\\\
3198 y = y + 1 \\\\\\\\\\\\\\\
3199 end\\\\\\\\\\\\\\\
3200 term.setBackgroundColor(c1)\\\\\\\\\\\\\\\
3201 term.setTextColor(c2)\\\\\\\\\\\\\\\
3202end\\\\\\\\\\\\\\\
3203\\\\\\\\\\\\\\\
3204local function boot_drawBootMenu(array, pos_x, pos_y, highlight, generic)\\\\\\\\\\\\\\\
3205 local select = 1\\\\\\\\\\\\\\\
3206 local x, y = term.getCursorPos()\\\\\\\\\\\\\\\
3207 \\\\\\\\\\\\\\\
3208 while true do\\\\\\\\\\\\\\\
3209 term.setCursorPos(x, y)\\\\\\\\\\\\\\\
3210 boot_mprint(array, select, pos_x, pos_y, highlight, generic)\\\\\\\\\\\\\\\
3211 event, key = os.pullEvent(\\\\\\\\\\\\\\\"key\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3212 --Enter\\\\\\\\\\\\\\\
3213 if key == 28 then \\\\\\\\\\\\\\\
3214 return select \\\\\\\\\\\\\\\
3215 end\\\\\\\\\\\\\\\
3216 \\\\\\\\\\\\\\\
3217 if #array > 1 then\\\\\\\\\\\\\\\
3218 --Arrow UP or W key\\\\\\\\\\\\\\\
3219 if key == 200 or key == 17 then \\\\\\\\\\\\\\\
3220 \\\\\\\\009\\\\\\\\009 select = select - 1 \\\\\\\\\\\\\\\
3221\\\\\\\\009\\\\\\\\009\\\\\\\\009\\\\\\\\\\\\\\\
3222 if select < 1 then \\\\\\\\\\\\\\\
3223 select = #array \\\\\\\\\\\\\\\
3224 end\\\\\\\\\\\\\\\
3225 --Arrow Down or S key\\\\\\\\\\\\\\\
3226 elseif key == 208 or key == 31 then \\\\\\\\\\\\\\\
3227 \\\\\\\\009\\\\\\\\009 select = select + 1 \\\\\\\\\\\\\\\
3228 \\\\\\\\009\\\\\\\\009\\\\\\\\009 if select > #array then select = 1 end\\\\\\\\\\\\\\\
3229 \\\\\\\\009 end\\\\\\\\\\\\\\\
3230 end \\\\\\\\\\\\\\\
3231 end\\\\\\\\\\\\\\\
3232end\\\\\\\\\\\\\\\
3233\\\\\\\\\\\\\\\
3234local function boot_printColoredTextLine(y, txt, bg, fg)\\\\\\\\\\\\\\\
3235 term.setCursorPos(1, y)\\\\\\\\\\\\\\\
3236 term.setBackgroundColor(bg or colors.lightGray)\\\\\\\\\\\\\\\
3237 term.write(\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3238 term.setCursorPos(1, y)\\\\\\\\\\\\\\\
3239 term.setTextColor(fg or colors.black)\\\\\\\\\\\\\\\
3240 print(txt)\\\\\\\\\\\\\\\
3241 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3242 term.setTextColor(colors.white)\\\\\\\\\\\\\\\
3243end\\\\\\\\\\\\\\\
3244\\\\\\\\\\\\\\\
3245__declare(\\\\\\\\\\\\\\\"drawBootManager\\\\\\\\\\\\\\\", nil)\\\\\\\\\\\\\\\
3246\\\\\\\\\\\\\\\
3247local function drawBootManager(opt)\\\\\\\\\\\\\\\
3248 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3249 term.clear()\\\\\\\\\\\\\\\
3250 term.setCursorPos(1,1)\\\\\\\\\\\\\\\
3251\\\\\\\\009if not opt then\\\\\\\\\\\\\\\
3252 boot_printColoredTextLine(2, \\\\\\\\\\\\\\\" Orbital Boot Manager v3.1 \\\\\\\\\\\\\\\", colors.lightGray, colors.black)\\\\\\\\\\\\\\\
3253 boot_printColoredTextLine(18, \\\\\\\\\\\\\\\" F2=ESI Setup F10=Boot Menu \\\\\\\\\\\\\\\", colors.lightGray, colors.black)\\\\\\\\\\\\\\\
3254\\\\\\\\009else\\\\\\\\\\\\\\\
3255 boot_printColoredTextLine(2, \\\\\\\\\\\\\\\" Orbital Boot Manager v3.1 \\\\\\\\\\\\\\\", colors.red, colors.black)\\\\\\\\\\\\\\\
3256 boot_printColoredTextLine(18, \\\\\\\\\\\\\\\" CTRL+R=Reboot \\\\\\\\\\\\\\\", colors.red, colors.black)\\\\\\\\\\\\\\\
3257\\\\\\\\009end\\\\\\\\\\\\\\\
3258end\\\\\\\\\\\\\\\
3259\\\\\\\\\\\\\\\
3260local esiTable = {}\\\\\\\\\\\\\\\
3261esiTable.UIBootMenu = boot_drawBootMenu\\\\\\\\\\\\\\\
3262esiTable.UIHandleElement = boot_handleBootElement\\\\\\\\\\\\\\\
3263esiTable.UIColoredLine = boot_printColoredTextLine\\\\\\\\\\\\\\\
3264esiTable.UIInit = drawBootManager\\\\\\\\\\\\\\\
3265esiTable.LoadBootConfig = function()\\\\\\\\\\\\\\\
3266 if not fs.exists(\\\\\\\\\\\\\\\"/boot/esi/config.dat\\\\\\\\\\\\\\\") then\\\\\\\\\\\\\\\
3267 return nil\\\\\\\\\\\\\\\
3268 end\\\\\\\\\\\\\\\
3269 local lf = fs.open(\\\\\\\\\\\\\\\"/boot/esi/config.dat\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"r\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3270 local contents = lf.readAll()\\\\\\\\\\\\\\\
3271 lf.close()\\\\\\\\\\\\\\\
3272 return textutils.unserialize(contents) \\\\\\\\\\\\\\\
3273end\\\\\\\\\\\\\\\
3274esiTable.SaveBootConfig = function(cTable)\\\\\\\\\\\\\\\
3275 local sf = fs.open(\\\\\\\\\\\\\\\"/boot/esi/config.dat\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"w\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3276 sf.write(textutils.serialize(cTable))\\\\\\\\\\\\\\\
3277 sf.close()\\\\\\\\\\\\\\\
3278 return true\\\\\\\\\\\\\\\
3279end\\\\\\\\\\\\\\\
3280esiTable.Finalize = function()\\\\\\\\\\\\\\\
3281__declare(\\\\\\\\\\\\\\\"RunInternal\\\\\\\\\\\\\\\", nil)\\\\\\\\\\\\\\\
3282__declare(\\\\\\\\\\\\\\\"RunMap\\\\\\\\\\\\\\\", nil)\\\\\\\\\\\\\\\
3283__declare(\\\\\\\\\\\\\\\"UserMode\\\\\\\\\\\\\\\", nil)\\\\\\\\\\\\\\\
3284__declare(\\\\\\\\\\\\\\\"Boot\\\\\\\\\\\\\\\", nil)\\\\\\\\\\\\\\\
3285__declare(\\\\\\\\\\\\\\\"RunExternal\\\\\\\\\\\\\\\", nil)\\\\\\\\\\\\\\\
3286__declare_api(\\\\\\\\\\\\\\\"ESI\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"Finalize\\\\\\\\\\\\\\\", nil)\\\\\\\\\\\\\\\
3287__declare_api(\\\\\\\\\\\\\\\"ESI\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"RunScript\\\\\\\\\\\\\\\", nil)\\\\\\\\\\\\\\\
3288end\\\\\\\\\\\\\\\
3289esiTable.RunScript = function(s)\\\\\\\\\\\\\\\
3290__declare(\\\\\\\\\\\\\\\"RunInternal\\\\\\\\\\\\\\\", function(m)\\\\\\\\\\\\\\\
3291 dofile(\\\\\\\\\\\\\\\"/boot/esi/\\\\\\\\\\\\\\\"..m..\\\\\\\\\\\\\\\".b\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3292end)\\\\\\\\\\\\\\\
3293__declare(\\\\\\\\\\\\\\\"RunMap\\\\\\\\\\\\\\\", function(m)\\\\\\\\\\\\\\\
3294 sr(\\\\\\\\\\\\\\\"/boot/\\\\\\\\\\\\\\\"..m..\\\\\\\\\\\\\\\".map\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3295end)\\\\\\\\\\\\\\\
3296__declare(\\\\\\\\\\\\\\\"UserMode\\\\\\\\\\\\\\\", function(null)\\\\\\\\\\\\\\\
3297 sr(\\\\\\\\\\\\\\\"/bin/sh\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3298end)\\\\\\\\\\\\\\\
3299__declare(\\\\\\\\\\\\\\\"Boot\\\\\\\\\\\\\\\", function(k)\\\\\\\\\\\\\\\
3300 dofile(\\\\\\\\\\\\\\\"/boot/kernel/\\\\\\\\\\\\\\\"..k)\\\\\\\\\\\\\\\
3301end)\\\\\\\\\\\\\\\
3302__declare(\\\\\\\\\\\\\\\"RunExternal\\\\\\\\\\\\\\\", function(f)\\\\\\\\\\\\\\\
3303 dofile(\\\\\\\\\\\\\\\"/boot/\\\\\\\\\\\\\\\"..f)\\\\\\\\\\\\\\\
3304end)\\\\\\\\\\\\\\\
3305sr(\\\\\\\\\\\\\\\"/boot/esi/scripts/\\\\\\\\\\\\\\\"..s..\\\\\\\\\\\\\\\".script\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3306end\\\\\\\\\\\\\\\
3307\\\\\\\\\\\\\\\
3308__declare(\\\\\\\\\\\\\\\"ESI\\\\\\\\\\\\\\\", esiTable)\\\\\\\\\\\\\\\
3309\\\\\\\\\\\\\\\
3310local conf = ESI.LoadBootConfig()\\\\\\\\\\\\\\\
3311\\\\\\\\\\\\\\\
3312if not conf then\\\\\\\\\\\\\\\
3313 ESI.SaveBootConfig(bootConfigDefaults)\\\\\\\\\\\\\\\
3314 drawBootManager(true)\\\\\\\\\\\\\\\
3315 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3316 term.setTextColor(colors.red)\\\\\\\\009\\\\\\\\\\\\\\\
3317\\\\\\\\009term.setCursorPos(2,4)\\\\\\\\\\\\\\\
3318\\\\\\\\009print(\\\\\\\\\\\\\\\"The Orbital Boot Manager was unable to continue\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3319\\\\\\\\009term.setCursorPos(2,5)\\\\\\\\\\\\\\\
3320\\\\\\\\009print(\\\\\\\\\\\\\\\"the booting process.\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3321\\\\\\\\009term.setCursorPos(2,7)\\\\\\\\\\\\\\\
3322\\\\\\\\009print(\\\\\\\\\\\\\\\"Status:\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3323\\\\\\\\009term.setCursorPos(2,8)\\\\\\\\\\\\\\\
3324\\\\\\\\009print(\\\\\\\\\\\\\\\"ESI_CONFIGURATION_MISSING (0x00000001)\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3325\\\\\\\\009term.setCursorPos(2,10)\\\\\\\\\\\\\\\
3326\\\\\\\\009print(\\\\\\\\\\\\\\\"Information:\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3327\\\\\\\\009term.setCursorPos(2,11)\\\\\\\\\\\\\\\
3328\\\\\\\\009print(\\\\\\\\\\\\\\\"The /boot/esi/config.dat file is missing.\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3329\\\\\\\\009term.setCursorPos(2,12)\\\\\\\\\\\\\\\
3330\\\\\\\\009print(\\\\\\\\\\\\\\\"A default file will be generated after rebooting.\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3331 while true do\\\\\\\\\\\\\\\
3332\\\\\\\\009 sleep(1)\\\\\\\\\\\\\\\
3333\\\\\\\\009end\\\\\\\\\\\\\\\
3334end\\\\\\\\\\\\\\\
3335\\\\\\\\\\\\\\\
3336local secondsPast = 0\\\\\\\\\\\\\\\
3337local timerID = os.startTimer( 1 )\\\\\\\\\\\\\\\
3338\\\\\\\\\\\\\\\
3339ESI.UIInit(false)\\\\\\\\\\\\\\\
3340term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3341term.setTextColor(colors.lightGray)\\\\\\\\009\\\\\\\\\\\\\\\
3342term.setCursorPos(2,4)\\\\\\\\\\\\\\\
3343print(\\\\\\\\\\\\\\\"Extensible System Interface (ESI)\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3344term.setCursorPos(2,6)\\\\\\\\\\\\\\\
3345print(\\\\\\\\\\\\\\\"Computer ID: \\\\\\\\\\\\\\\"..tostring(os.getComputerID()))\\\\\\\\\\\\\\\
3346term.setCursorPos(2,7)\\\\\\\\\\\\\\\
3347print(\\\\\\\\\\\\\\\"Hostname: \\\\\\\\\\\\\\\"..tostring(os.getComputerLabel() or \\\\\\\\\\\\\\\"N/A\\\\\\\\\\\\\\\"))\\\\\\\\\\\\\\\
3348\\\\\\\\\\\\\\\
3349sleep(0.25)\\\\\\\\\\\\\\\
3350\\\\\\\\\\\\\\\
3351for k, file in pairs(fs.list(\\\\\\\\\\\\\\\"/boot/esi/drivers\\\\\\\\\\\\\\\")) do\\\\\\\\\\\\\\\
3352 if not dofile(\\\\\\\\\\\\\\\"/boot/esi/drivers/\\\\\\\\\\\\\\\"..file) then\\\\\\\\\\\\\\\
3353 drawBootManager(true)\\\\\\\\\\\\\\\
3354 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3355 term.setTextColor(colors.red)\\\\\\\\009\\\\\\\\\\\\\\\
3356\\\\\\\\009term.setCursorPos(2,4)\\\\\\\\\\\\\\\
3357\\\\\\\\009print(\\\\\\\\\\\\\\\"The Orbital Boot Manager was unable to continue\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3358\\\\\\\\009term.setCursorPos(2,5)\\\\\\\\\\\\\\\
3359\\\\\\\\009print(\\\\\\\\\\\\\\\"the booting process.\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3360\\\\\\\\009term.setCursorPos(2,7)\\\\\\\\\\\\\\\
3361\\\\\\\\009print(\\\\\\\\\\\\\\\"Status:\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3362\\\\\\\\009term.setCursorPos(2,8)\\\\\\\\\\\\\\\
3363\\\\\\\\009print(\\\\\\\\\\\\\\\"DRIVER_LOAD_FAILURE (0x00000003)\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3364\\\\\\\\009term.setCursorPos(2,10)\\\\\\\\\\\\\\\
3365\\\\\\\\009print(\\\\\\\\\\\\\\\"Information:\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3366\\\\\\\\009term.setCursorPos(2,11)\\\\\\\\\\\\\\\
3367\\\\\\\\009print(\\\\\\\\\\\\\\\"The following driver failed to load:\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3368\\\\\\\\009term.setCursorPos(2,12)\\\\\\\\\\\\\\\
3369\\\\\\\\009print(\\\\\\\\\\\\\\\"/boot/esi/drivers/\\\\\\\\\\\\\\\"..file)\\\\\\\\\\\\\\\
3370 while true do\\\\\\\\\\\\\\\
3371\\\\\\\\009 sleep(1)\\\\\\\\\\\\\\\
3372\\\\\\\\009end\\\\\\\\\\\\\\\
3373 else\\\\\\\\\\\\\\\
3374 term.setCursorPos(2,8+k) \\\\\\\\\\\\\\\
3375 print(\\\\\\\\\\\\\\\"Loaded driver: \\\\\\\\\\\\\\\"..file)\\\\\\\\\\\\\\\
3376 end\\\\\\\\\\\\\\\
3377end\\\\\\\\\\\\\\\
3378\\\\\\\\\\\\\\\
3379sleep(0.25)\\\\\\\\\\\\\\\
3380\\\\\\\\\\\\\\\
3381term.setCursorPos(2,16)\\\\\\\\\\\\\\\
3382print(\\\\\\\\\\\\\\\"Booting active kernel...\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3383\\\\\\\\\\\\\\\
3384while true do\\\\\\\\\\\\\\\
3385 local event, value = os.pullEvent()\\\\\\\\\\\\\\\
3386 --sleep(0.1)\\\\\\\\\\\\\\\
3387 if event == \\\\\\\\\\\\\\\"timer\\\\\\\\\\\\\\\" and value == timerID then\\\\\\\\\\\\\\\
3388 secondsPast = secondsPast + 1 -- Increment secondsPast by one, a second has passed\\\\\\\\\\\\\\\
3389 if secondsPast == 3 then\\\\\\\\\\\\\\\
3390 --sleep(0.1)\\\\\\\\\\\\\\\
3391 ESI.UIColoredLine(18, \\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\", colors.lightGray, colors.black)\\\\\\\\\\\\\\\
3392 break\\\\\\\\\\\\\\\
3393 else\\\\\\\\\\\\\\\
3394 timerID = os.startTimer( 1 )\\\\\\\\\\\\\\\
3395 end\\\\\\\\\\\\\\\
3396 elseif event == \\\\\\\\\\\\\\\"key\\\\\\\\\\\\\\\" and value == 60 then\\\\\\\\\\\\\\\
3397 break\\\\\\\\\\\\\\\
3398 end\\\\\\\\\\\\\\\
3399end\\\\\\\\\\\\\\\
3400\\\\\\\\\\\\\\\
3401if secondsPast == 3 then\\\\\\\\\\\\\\\
3402 ESI.RunScript(conf.script)\\\\\\\\\\\\\\\
3403else\\\\\\\\\\\\\\\
3404 --sr(\\\\\\\\\\\\\\\"esiconfig\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3405end\\\\\\\"\\\",\\\
3406 \\\"F:esiconfig.b\\\",\\\
3407 \\\"\\\\\\\"local function boot_handleBootElement(str)\\\\\\\\\\\\\\\
3408 local s1 = \\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\
3409 local n1 = s1:len()\\\\\\\\\\\\\\\
3410 local n2 = str:len()\\\\\\\\\\\\\\\
3411 local s2 = string.sub(s1, 1, n1-n2)\\\\\\\\\\\\\\\
3412 return \\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"..str..s2..\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\
3413end\\\\\\\\\\\\\\\
3414\\\\\\\\\\\\\\\
3415local function boot_mprint(array, this, x, y, h, g)\\\\\\\\\\\\\\\
3416 local c1 = term.getBackgroundColor()\\\\\\\\\\\\\\\
3417 local c2 = term.getTextColor()\\\\\\\\\\\\\\\
3418 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3419 for i = 1, #array do\\\\\\\\\\\\\\\
3420 term.setCursorPos(x, y)\\\\\\\\\\\\\\\
3421 --Check if option selected\\\\\\\\\\\\\\\
3422 if i == this then \\\\\\\\\\\\\\\
3423 --Option selected \\\\\\\\\\\\\\\
3424 term.setBackgroundColor(h)\\\\\\\\\\\\\\\
3425 term.setTextColor(g)\\\\\\\\\\\\\\\
3426 else \\\\\\\\\\\\\\\
3427 --Option NOT selected \\\\\\\\\\\\\\\
3428 term.setBackgroundColor(g)\\\\\\\\\\\\\\\
3429 term.setTextColor(h)\\\\\\\\\\\\\\\
3430 end\\\\\\\\\\\\\\\
3431 --Print the string\\\\\\\\\\\\\\\
3432 term.write(boot_handleBootElement(array[i]))\\\\\\\\\\\\\\\
3433 y = y + 1 \\\\\\\\\\\\\\\
3434 end\\\\\\\\\\\\\\\
3435 term.setBackgroundColor(c1)\\\\\\\\\\\\\\\
3436 term.setTextColor(c2)\\\\\\\\\\\\\\\
3437end\\\\\\\\\\\\\\\
3438\\\\\\\\\\\\\\\
3439local function boot_drawBootMenu(array, pos_x, pos_y, highlight, generic)\\\\\\\\\\\\\\\
3440 local select = 1\\\\\\\\\\\\\\\
3441 local x, y = term.getCursorPos()\\\\\\\\\\\\\\\
3442 \\\\\\\\\\\\\\\
3443 while true do\\\\\\\\\\\\\\\
3444 term.setCursorPos(x, y)\\\\\\\\\\\\\\\
3445 boot_mprint(array, select, pos_x, pos_y, highlight, generic)\\\\\\\\\\\\\\\
3446 event, key = os.pullEvent(\\\\\\\\\\\\\\\"key\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3447 --Enter\\\\\\\\\\\\\\\
3448 if key == 28 then \\\\\\\\\\\\\\\
3449 return select \\\\\\\\\\\\\\\
3450 end\\\\\\\\\\\\\\\
3451 \\\\\\\\\\\\\\\
3452 if #array > 1 then\\\\\\\\\\\\\\\
3453 --Arrow UP or W key\\\\\\\\\\\\\\\
3454 if key == 200 or key == 17 then \\\\\\\\\\\\\\\
3455 \\\\\\\\009\\\\\\\\009 select = select - 1 \\\\\\\\\\\\\\\
3456\\\\\\\\009\\\\\\\\009\\\\\\\\009\\\\\\\\\\\\\\\
3457 if select < 1 then \\\\\\\\\\\\\\\
3458 select = #array \\\\\\\\\\\\\\\
3459 end\\\\\\\\\\\\\\\
3460 --Arrow Down or S key\\\\\\\\\\\\\\\
3461 elseif key == 208 or key == 31 then \\\\\\\\\\\\\\\
3462 \\\\\\\\009\\\\\\\\009 select = select + 1 \\\\\\\\\\\\\\\
3463 \\\\\\\\009\\\\\\\\009\\\\\\\\009 if select > #array then select = 1 end\\\\\\\\\\\\\\\
3464 \\\\\\\\009 end\\\\\\\\\\\\\\\
3465 end \\\\\\\\\\\\\\\
3466 end\\\\\\\\\\\\\\\
3467end\\\\\\\\\\\\\\\
3468\\\\\\\\\\\\\\\
3469term.clear()\\\\\\\\\\\\\\\
3470boot_drawBootMenu({boot_handleBootElement(\\\\\\\\\\\\\\\"Darwin Developer Preview 0.1.0.7\\\\\\\\\\\\\\\"), boot_handleBootElement(\\\\\\\\\\\\\\\"Tesseract Bootstrap 1.0.0.0\\\\\\\\\\\\\\\"), boot_handleBootElement(\\\\\\\\\\\\\\\"aaaaaaaaaa\\\\\\\\\\\\\\\")}, 2, 2, colors.lightGray, colors.black)\\\\\\\"\\\",\\\
3471 \\\"D:scripts\\\",\\\
3472 \\\"{\\\\\\\
3473 \\\\\\\"F:Orbital.script\\\\\\\",\\\\\\\
3474 \\\\\\\"\\\\\\\\\\\\\\\"-- Example ESI boot script.\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3475\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3476RunMap \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"kernel\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" -- run kernel.map\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3477RunMap \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"security\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" -- run security.map\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3478Boot \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"darwin-rolling-0.1.0.7\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" -- boot the kernel\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
3479UserMode \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"Default\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" -- go user mode\\\\\\\\\\\\\\\"\\\\\\\",\\\\\\\
3480}\\\",\\\
3481}\",\
3482 \"D:kernel\",\
3483 \"{\\\
3484 \\\"F:darwin-rolling-0.1.0.7\\\",\\\
3485 \\\"\\\\\\\"-- @PRODUCTNAME Darwin\\\\\\\\\\\\\\\
3486-- @VERSION 0.0.4.6\\\\\\\\\\\\\\\
3487-- @RELEASETYPE rolling\\\\\\\\\\\\\\\
3488-- @SKU Developer Preview\\\\\\\\\\\\\\\
3489\\\\\\\\\\\\\\\
3490--term.clear()\\\\\\\\\\\\\\\
3491\\\\\\\\\\\\\\\
3492os.version = function()\\\\\\\\\\\\\\\
3493 return \\\\\\\\\\\\\\\"Orbital 0.1.0.7 Developer Preview\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\
3494end\\\\\\\\\\\\\\\
3495\\\\\\\\\\\\\\\
3496if not dofile(\\\\\\\\\\\\\\\"/boot/kernel.map\\\\\\\\\\\\\\\") then\\\\\\\\\\\\\\\
3497 printError(\\\\\\\\\\\\\\\"[ X ] Failed to initialize kernel library\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3498 while true do\\\\\\\\\\\\\\\
3499 coroutine.yield()\\\\\\\\\\\\\\\
3500 end\\\\\\\\\\\\\\\
3501end\\\\\\\\\\\\\\\
3502\\\\\\\\\\\\\\\
3503__declare(\\\\\\\\\\\\\\\"__DEBUG\\\\\\\\\\\\\\\", __kstruct({true}))\\\\\\\\\\\\\\\
3504\\\\\\\\\\\\\\\
3505n = 1\\\\\\\\\\\\\\\
3506for k, file in pairs(fs.list(\\\\\\\\\\\\\\\"/lib\\\\\\\\\\\\\\\")) do\\\\\\\\\\\\\\\
3507 if string.sub(file, -3) == \\\\\\\\\\\\\\\".so\\\\\\\\\\\\\\\" and file ~= \\\\\\\\\\\\\\\"libstdlua.2.so\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\
3508 term.setCursorPos(2,3 + n)\\\\\\\\\\\\\\\
3509 __kload(\\\\\\\\\\\\\\\"/lib/\\\\\\\\\\\\\\\"..file) -- attempting to hook the file\\\\\\\\\\\\\\\
3510 n = k\\\\\\\\\\\\\\\
3511 else\\\\\\\\\\\\\\\
3512 n = k - 1\\\\\\\\\\\\\\\
3513 end\\\\\\\\\\\\\\\
3514end\\\\\\\\\\\\\\\
3515\\\\\\\\\\\\\\\
3516-- finalize kernel-mode init\\\\\\\\\\\\\\\
3517__kfinalize()\\\\\\\\\\\\\\\
3518\\\\\\\\\\\\\\\
3519sleep(0.5)\\\\\\\\\\\\\\\
3520\\\\\\\\\\\\\\\
3521-- output\\\\\\\\\\\\\\\
3522--term.setCursorPos(2,8)\\\\\\\\\\\\\\\
3523--printk(1, \\\\\\\\\\\\\\\"Darwin kernel loaded\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3524\\\\\\\\\\\\\\\
3525sleep(2)\\\\\\\\\\\\\\\
3526\\\\\\\\\\\\\\\
3527term.clear()\\\\\\\\\\\\\\\
3528term.setCursorPos(1,1)\\\\\\\"\\\",\\\
3529 \\\"F:tesseract-bootstrap-1.0\\\",\\\
3530 \\\"\\\\\\\"-- @PRODUCTNAME Tesseract\\\\\\\\\\\\\\\
3531-- @VERSION 1.0.0.0\\\\\\\\\\\\\\\
3532-- @RELEASETYPE release\\\\\\\\\\\\\\\
3533-- @SKU Bootstrap\\\\\\\\\\\\\\\
3534\\\\\\\\\\\\\\\
3535local temp_kernel = [[\\\\\\\\\\\\\\\
3536-- Halt the system completely, yield all coroutines\\\\\\\\\\\\\\\
3537local function halt()\\\\\\\\\\\\\\\
3538 while true do\\\\\\\\\\\\\\\
3539 coroutine.create(function() while true do coroutine.yield() end end)\\\\\\\\\\\\\\\
3540 coroutine.yield()\\\\\\\\\\\\\\\
3541 end\\\\\\\\\\\\\\\
3542end\\\\\\\\\\\\\\\
3543\\\\\\\\\\\\\\\
3544-- Low-level routines\\\\\\\\\\\\\\\
3545function traverseKey(array, text)\\\\\\\\\\\\\\\
3546 for k,v in pairs(array) do\\\\\\\\\\\\\\\
3547 if v == text then\\\\\\\\\\\\\\\
3548 return true, k\\\\\\\\\\\\\\\
3549 end\\\\\\\\\\\\\\\
3550 end\\\\\\\\\\\\\\\
3551 return false, nil\\\\\\\\\\\\\\\
3552end\\\\\\\\\\\\\\\
3553\\\\\\\\\\\\\\\
3554function traverseValue(array, text)\\\\\\\\\\\\\\\
3555 for k,v in pairs(array) do\\\\\\\\\\\\\\\
3556 if k == text then\\\\\\\\\\\\\\\
3557 return true, v\\\\\\\\\\\\\\\
3558 end\\\\\\\\\\\\\\\
3559 end\\\\\\\\\\\\\\\
3560 return false, nil\\\\\\\\\\\\\\\
3561end\\\\\\\\\\\\\\\
3562\\\\\\\\\\\\\\\
3563function findKey(array, text)\\\\\\\\\\\\\\\
3564 for k,v in pairs(array) do\\\\\\\\\\\\\\\
3565 if k == text then\\\\\\\\\\\\\\\
3566 return true, k\\\\\\\\\\\\\\\
3567 end\\\\\\\\\\\\\\\
3568 end\\\\\\\\\\\\\\\
3569 return false, nil\\\\\\\\\\\\\\\
3570end\\\\\\\\\\\\\\\
3571\\\\\\\\\\\\\\\
3572function findValue(array, text)\\\\\\\\\\\\\\\
3573 for k,v in pairs(array) do\\\\\\\\\\\\\\\
3574 if v == text then\\\\\\\\\\\\\\\
3575 return true, v\\\\\\\\\\\\\\\
3576 end\\\\\\\\\\\\\\\
3577 end\\\\\\\\\\\\\\\
3578 return false, nil\\\\\\\\\\\\\\\
3579end\\\\\\\\\\\\\\\
3580\\\\\\\\\\\\\\\
3581function queryForKey(array, text)\\\\\\\\\\\\\\\
3582 for k,v in pairs(array) do\\\\\\\\\\\\\\\
3583 if string.find(k, text) then\\\\\\\\\\\\\\\
3584 return true, k\\\\\\\\\\\\\\\
3585 end\\\\\\\\\\\\\\\
3586 end\\\\\\\\\\\\\\\
3587 return false, nil\\\\\\\\\\\\\\\
3588end\\\\\\\\\\\\\\\
3589\\\\\\\\\\\\\\\
3590function queryForValue(array, text)\\\\\\\\\\\\\\\
3591 for k,v in pairs(array) do\\\\\\\\\\\\\\\
3592 if string.find(v, text) then\\\\\\\\\\\\\\\
3593 return true, v\\\\\\\\\\\\\\\
3594 end\\\\\\\\\\\\\\\
3595 end\\\\\\\\\\\\\\\
3596 return false, nil\\\\\\\\\\\\\\\
3597end\\\\\\\\\\\\\\\
3598\\\\\\\\\\\\\\\
3599function stringToBytes(str)\\\\\\\\\\\\\\\
3600 return string.byte(str, 1, str:len())\\\\\\\\\\\\\\\
3601end\\\\\\\\\\\\\\\
3602\\\\\\\\\\\\\\\
3603function bytesToString(...)\\\\\\\\\\\\\\\
3604 return string.char(...)\\\\\\\\\\\\\\\
3605end\\\\\\\\\\\\\\\
3606\\\\\\\\\\\\\\\
3607function iterateFileLines(path)\\\\\\\\\\\\\\\
3608 local handle = fs.open(path, \\\\\\\\\\\\\\\"r\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3609 local commands = {}\\\\\\\\\\\\\\\
3610 local line = handle.readLine()\\\\\\\\\\\\\\\
3611 while line do\\\\\\\\\\\\\\\
3612 commands[#commands + 1] = line\\\\\\\\\\\\\\\
3613 line = handle.readLine()\\\\\\\\\\\\\\\
3614 end\\\\\\\\\\\\\\\
3615 handle.close()\\\\\\\\\\\\\\\
3616 return commands\\\\\\\\\\\\\\\
3617end\\\\\\\\\\\\\\\
3618\\\\\\\\\\\\\\\
3619-- Clear the screen\\\\\\\\\\\\\\\
3620function clear()\\\\\\\\\\\\\\\
3621 term.clear()\\\\\\\\\\\\\\\
3622 term.setCursorPos(1,1)\\\\\\\\\\\\\\\
3623end\\\\\\\\\\\\\\\
3624\\\\\\\\\\\\\\\
3625-- Shut the system down safely.\\\\\\\\\\\\\\\
3626function shutdown()\\\\\\\\\\\\\\\
3627 gui.printBootSuccess(\\\\\\\\\\\\\\\"System is ready for shutdown\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3628 sleep(1.5)\\\\\\\\\\\\\\\
3629 os.shutdown()\\\\\\\\\\\\\\\
3630 halt()\\\\\\\\\\\\\\\
3631end\\\\\\\\\\\\\\\
3632\\\\\\\\\\\\\\\
3633function reboot()\\\\\\\\\\\\\\\
3634 gui.printBootSuccess(\\\\\\\\\\\\\\\"System is rebooting\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3635 sleep(1.5)\\\\\\\\\\\\\\\
3636 os.reboot()\\\\\\\\\\\\\\\
3637 halt()\\\\\\\\\\\\\\\
3638end\\\\\\\\\\\\\\\
3639\\\\\\\\\\\\\\\
3640-- Crash the system\\\\\\\\\\\\\\\
3641function crashReport(text)\\\\\\\\\\\\\\\
3642 printError(\\\\\\\\\\\\\\\"[ ! ] Fatal error (\\\\\\\\\\\\\\\"..text..\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3643 printError(\\\\\\\\\\\\\\\"[ ! ] HALTING EXECUTION!\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3644 halt()\\\\\\\\\\\\\\\
3645end\\\\\\\\\\\\\\\
3646\\\\\\\\\\\\\\\
3647-- Import a file\\\\\\\\\\\\\\\
3648function import(file)\\\\\\\\\\\\\\\
3649 if fs.exists(file) and not fs.isDir(file) then\\\\\\\\\\\\\\\
3650 return os.loadAPI(file)\\\\\\\\\\\\\\\
3651 else\\\\\\\\\\\\\\\
3652 log.write(\\\\\\\\\\\\\\\"Failed to load \\\\\\\\\\\\\\\"..file..\\\\\\\\\\\\\\\" as an API\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3653 return false\\\\\\\\\\\\\\\
3654 end\\\\\\\\\\\\\\\
3655end\\\\\\\\\\\\\\\
3656\\\\\\\\\\\\\\\
3657-- Require a file as a Lua module\\\\\\\\\\\\\\\
3658function require(file) -- A primitive require\\\\\\\\\\\\\\\
3659 if fs.exists(file) and not fs.isDir(file) then\\\\\\\\\\\\\\\
3660 return dofile(file)\\\\\\\\\\\\\\\
3661 else\\\\\\\\\\\\\\\
3662 log.write(\\\\\\\\\\\\\\\"Failed to load \\\\\\\\\\\\\\\"..file..\\\\\\\\\\\\\\\" as an module\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3663 return nil\\\\\\\\\\\\\\\
3664 end\\\\\\\\\\\\\\\
3665end\\\\\\\\\\\\\\\
3666\\\\\\\\\\\\\\\
3667-- API hook\\\\\\\\\\\\\\\
3668function APIHook(t)\\\\\\\\\\\\\\\
3669 if t then\\\\\\\\\\\\\\\
3670 return true\\\\\\\\\\\\\\\
3671 else\\\\\\\\\\\\\\\
3672 -- Not loaded\\\\\\\\\\\\\\\
3673 if import(\\\\\\\\\\\\\\\"/system/api/\\\\\\\\\\\\\\\"..t) then\\\\\\\\\\\\\\\
3674 return true\\\\\\\\\\\\\\\
3675 end\\\\\\\\\\\\\\\
3676 end\\\\\\\\\\\\\\\
3677 return false\\\\\\\\\\\\\\\
3678end\\\\\\\\\\\\\\\
3679\\\\\\\\\\\\\\\
3680-- Load system libraries\\\\\\\\\\\\\\\
3681function loadAssemblies(dir)\\\\\\\\\\\\\\\
3682 local flist = fs.list(dir)\\\\\\\\\\\\\\\
3683 for _, file in ipairs(flist) do\\\\\\\\\\\\\\\
3684 sleep(0.25)\\\\\\\\\\\\\\\
3685 kernel.import(dir..\\\\\\\\\\\\\\\"/\\\\\\\\\\\\\\\"..file) -- attempting to hook the file\\\\\\\\\\\\\\\
3686 gui.printBootSuccess(\\\\\\\\\\\\\\\"Assembly \\\\\\\\\\\\\\\"..file..\\\\\\\\\\\\\\\" hooked into RAM!\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3687 end\\\\\\\\\\\\\\\
3688end\\\\\\\\\\\\\\\
3689\\\\\\\\\\\\\\\
3690function printFile(file)\\\\\\\\\\\\\\\
3691 if fs.exists(file) and not fs.isDir(file) then\\\\\\\\\\\\\\\
3692 local handle = fs.open(file, \\\\\\\\\\\\\\\"r\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3693 local contents = handle.readAll()\\\\\\\\\\\\\\\
3694 handle.close()\\\\\\\\\\\\\\\
3695 return contents\\\\\\\\\\\\\\\
3696 end\\\\\\\\\\\\\\\
3697end\\\\\\\\\\\\\\\
3698\\\\\\\\\\\\\\\
3699function getURLContents(url)\\\\\\\\\\\\\\\
3700 local handlex = http.get(url)\\\\\\\\\\\\\\\
3701 local contents = handlex.readAll()\\\\\\\\\\\\\\\
3702 handlex.close()\\\\\\\\\\\\\\\
3703 return contents\\\\\\\\\\\\\\\
3704end\\\\\\\\\\\\\\\
3705\\\\\\\\\\\\\\\
3706function getFile(file, url, overwrite)\\\\\\\\\\\\\\\
3707 if not fs.exists(file) then\\\\\\\\\\\\\\\
3708 local handle = fs.open(file, \\\\\\\\\\\\\\\"w\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3709 handle.writeLine(getURLContents(url))\\\\\\\\\\\\\\\
3710 handle.close()\\\\\\\\\\\\\\\
3711 return true\\\\\\\\\\\\\\\
3712 elseif overwrite and not fs.isDir(file) then\\\\\\\\\\\\\\\
3713 local handle = fs.open(file, \\\\\\\\\\\\\\\"w\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3714 handle.writeLine(getURLContents(url))\\\\\\\\\\\\\\\
3715 handle.close()\\\\\\\\\\\\\\\
3716 return true\\\\\\\\\\\\\\\
3717 end\\\\\\\\\\\\\\\
3718 return false\\\\\\\\\\\\\\\
3719end\\\\\\\\\\\\\\\
3720\\\\\\\\\\\\\\\
3721function secureInput(invite, definition)\\\\\\\\\\\\\\\
3722 write(invite..\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3723 local input = read(\\\\\\\\\\\\\\\"*\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3724 if input == definition then\\\\\\\\\\\\\\\
3725 return true\\\\\\\\\\\\\\\
3726 else\\\\\\\\\\\\\\\
3727 return false\\\\\\\\\\\\\\\
3728 end\\\\\\\\\\\\\\\
3729end\\\\\\\\\\\\\\\
3730]]\\\\\\\\\\\\\\\
3731\\\\\\\\\\\\\\\
3732local temp_gui = [[\\\\\\\\\\\\\\\
3733function clearScreen(color)\\\\\\\\\\\\\\\
3734 term.setBackgroundColor(color or colors.black)\\\\\\\\\\\\\\\
3735 kernel.clear()\\\\\\\\\\\\\\\
3736end\\\\\\\\\\\\\\\
3737\\\\\\\\\\\\\\\
3738function button(text, x1, x2, y)\\\\\\\\\\\\\\\
3739 term.setCursorPos(x1, y)\\\\\\\\\\\\\\\
3740 print(text)\\\\\\\\\\\\\\\
3741 local a, b, xx, yy = os.pullEvent(\\\\\\\\\\\\\\\"mouse_click\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3742 if (xx >= x1 and xx <= x2 and yy == y) then\\\\\\\\\\\\\\\
3743 return true\\\\\\\\\\\\\\\
3744 else\\\\\\\\\\\\\\\
3745 return false\\\\\\\\\\\\\\\
3746 end\\\\\\\\\\\\\\\
3747end\\\\\\\\\\\\\\\
3748\\\\\\\\\\\\\\\
3749function counter(text, y)\\\\\\\\\\\\\\\
3750 for i=1,100 do\\\\\\\\\\\\\\\
3751 sleep(0.1)\\\\\\\\\\\\\\\
3752 term.setCursorPos(1, y)\\\\\\\\\\\\\\\
3753 print(text..\\\\\\\\\\\\\\\" [\\\\\\\\\\\\\\\"..tostring(i)..\\\\\\\\\\\\\\\"%]\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3754 end\\\\\\\\\\\\\\\
3755end\\\\\\\\\\\\\\\
3756\\\\\\\\\\\\\\\
3757function drawProgress(txt, y)\\\\\\\\\\\\\\\
3758 term.setCursorPos(4, 4)\\\\\\\\\\\\\\\
3759 print(txt)\\\\\\\\\\\\\\\
3760 term.setCursorPos(1, y)\\\\\\\\\\\\\\\
3761 print(\\\\\\\\\\\\\\\"[ ]\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3762 term.setCursorPos(2, y)\\\\\\\\\\\\\\\
3763 textutils.slowPrint(\\\\\\\\\\\\\\\"==============================]\\\\\\\\\\\\\\\", 10)\\\\\\\\\\\\\\\
3764end\\\\\\\\\\\\\\\
3765\\\\\\\\\\\\\\\
3766function drawProgressAlt(color)\\\\\\\\\\\\\\\
3767 term.setCursorPos(4, 10)\\\\\\\\\\\\\\\
3768 print(\\\\\\\\\\\\\\\"#-------------------------------------------#\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3769 term.setCursorPos(4, 11)\\\\\\\\\\\\\\\
3770 print(\\\\\\\\\\\\\\\"| |\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3771 term.setCursorPos(4, 12)\\\\\\\\\\\\\\\
3772 print(\\\\\\\\\\\\\\\"#-------------------------------------------#\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3773 term.setBackgroundColor(color or colors.yellow)\\\\\\\\\\\\\\\
3774 term.setCursorPos(5, 11)\\\\\\\\\\\\\\\
3775 textutils.slowWrite(\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\", 10)\\\\\\\\\\\\\\\
3776 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3777end\\\\\\\\\\\\\\\
3778\\\\\\\\\\\\\\\
3779function printColoredTextLine(y, txt, bg, fg)\\\\\\\\\\\\\\\
3780 term.setCursorPos(1, y)\\\\\\\\\\\\\\\
3781 term.setBackgroundColor(bg or colors.lightGray)\\\\\\\\\\\\\\\
3782 term.write(\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3783 term.setCursorPos(1, y)\\\\\\\\\\\\\\\
3784 term.setTextColor(fg or colors.black)\\\\\\\\\\\\\\\
3785 print(txt)\\\\\\\\\\\\\\\
3786 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3787 term.setTextColor(colors.white)\\\\\\\\\\\\\\\
3788end\\\\\\\\\\\\\\\
3789\\\\\\\\\\\\\\\
3790function printBootInfo(i)\\\\\\\\\\\\\\\
3791 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3792 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3793 write(\\\\\\\\\\\\\\\"[ \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3794 term.setTextColor(colors.cyan)\\\\\\\\\\\\\\\
3795 write(\\\\\\\\\\\\\\\"* \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3796 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3797 write(\\\\\\\\\\\\\\\"] \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3798 print(\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"..i)\\\\\\\\\\\\\\\
3799 term.setTextColor(colors.white)\\\\\\\\\\\\\\\
3800end\\\\\\\\\\\\\\\
3801\\\\\\\\\\\\\\\
3802function printBootWarning(w)\\\\\\\\\\\\\\\
3803 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3804 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3805 write(\\\\\\\\\\\\\\\"[ \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3806 term.setTextColor(colors.orange)\\\\\\\\\\\\\\\
3807 write(\\\\\\\\\\\\\\\"! \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3808 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3809 write(\\\\\\\\\\\\\\\"] \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3810 print(\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"..w)\\\\\\\\\\\\\\\
3811 term.setTextColor(colors.white)\\\\\\\\\\\\\\\
3812end\\\\\\\\\\\\\\\
3813\\\\\\\\\\\\\\\
3814function printBootSuccess(wa)\\\\\\\\\\\\\\\
3815 term.setBackgroundColor(colors.black)\\\\\\\\\\\\\\\
3816 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3817 write(\\\\\\\\\\\\\\\"[ \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3818 term.setTextColor(colors.lime)\\\\\\\\\\\\\\\
3819 write(\\\\\\\\\\\\\\\"v \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3820 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3821 write(\\\\\\\\\\\\\\\"] \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3822 print(\\\\\\\\\\\\\\\" \\\\\\\\\\\\\\\"..wa)\\\\\\\\\\\\\\\
3823 term.setTextColor(colors.white)\\\\\\\\\\\\\\\
3824end\\\\\\\\\\\\\\\
3825\\\\\\\\\\\\\\\
3826function printAppInfo(header, msg)\\\\\\\\\\\\\\\
3827 term.setTextColor(colors.cyan)\\\\\\\\\\\\\\\
3828 write(header..\\\\\\\\\\\\\\\": \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3829 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3830 print(msg)\\\\\\\\\\\\\\\
3831 term.setTextColor(colors.white)\\\\\\\\\\\\\\\
3832end\\\\\\\\\\\\\\\
3833\\\\\\\\\\\\\\\
3834function printAppWarning(header, msg)\\\\\\\\\\\\\\\
3835 term.setTextColor(colors.red)\\\\\\\\\\\\\\\
3836 write(header..\\\\\\\\\\\\\\\": \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3837 term.setTextColor(colors.orange)\\\\\\\\\\\\\\\
3838 print(msg)\\\\\\\\\\\\\\\
3839 term.setTextColor(colors.white)\\\\\\\\\\\\\\\
3840end\\\\\\\\\\\\\\\
3841\\\\\\\\\\\\\\\
3842function printAppSuccess(header, msg)\\\\\\\\\\\\\\\
3843 term.setTextColor(colors.lime)\\\\\\\\\\\\\\\
3844 write(header..\\\\\\\\\\\\\\\": \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3845 term.setTextColor(colors.green)\\\\\\\\\\\\\\\
3846 print(msg)\\\\\\\\\\\\\\\
3847 term.setTextColor(colors.white)\\\\\\\\\\\\\\\
3848end\\\\\\\\\\\\\\\
3849\\\\\\\\\\\\\\\
3850function request(req)\\\\\\\\\\\\\\\
3851 while true do\\\\\\\\\\\\\\\
3852 term.setTextColor(colors.cyan)\\\\\\\\\\\\\\\
3853 write(req .. \\\\\\\\\\\\\\\"? \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3854 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3855 write(\\\\\\\\\\\\\\\"(\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3856 term.setTextColor(colors.lime)\\\\\\\\\\\\\\\
3857 write(\\\\\\\\\\\\\\\"Y\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3858 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3859 write(\\\\\\\\\\\\\\\"/\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3860 term.setTextColor(colors.red)\\\\\\\\\\\\\\\
3861 write(\\\\\\\\\\\\\\\"N\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3862 term.setTextColor(colors.lightGray)\\\\\\\\\\\\\\\
3863 write(\\\\\\\\\\\\\\\") \\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3864 local presel=read()\\\\\\\\\\\\\\\
3865 if presel==\\\\\\\\\\\\\\\"Y\\\\\\\\\\\\\\\" or presel==\\\\\\\\\\\\\\\"y\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\
3866 return true\\\\\\\\\\\\\\\
3867 elseif presel==\\\\\\\\\\\\\\\"N\\\\\\\\\\\\\\\" or presel==\\\\\\\\\\\\\\\"n\\\\\\\\\\\\\\\" then\\\\\\\\\\\\\\\
3868 return false\\\\\\\\\\\\\\\
3869 end\\\\\\\\\\\\\\\
3870 end\\\\\\\\\\\\\\\
3871end\\\\\\\\\\\\\\\
3872\\\\\\\\\\\\\\\
3873function drawImg(path, x, y)\\\\\\\\\\\\\\\
3874 if fs.exists(path) and not fs.isDir(path) then\\\\\\\\\\\\\\\
3875 local img = paintutils.loadImage(path)\\\\\\\\\\\\\\\
3876 paintutils.drawImage(img, x, y)\\\\\\\\\\\\\\\
3877 else\\\\\\\\\\\\\\\
3878 gui.printAppWarning(\\\\\\\\\\\\\\\"gui\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"image not found\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3879 end\\\\\\\\\\\\\\\
3880end\\\\\\\\\\\\\\\
3881\\\\\\\\\\\\\\\
3882function printColored(text, color)\\\\\\\\\\\\\\\
3883 local tmp = term.getTextColor()\\\\\\\\\\\\\\\
3884 term.setTextColor(color)\\\\\\\\\\\\\\\
3885 print(text)\\\\\\\\\\\\\\\
3886 term.setTextColor(tmp)\\\\\\\\\\\\\\\
3887end\\\\\\\\\\\\\\\
3888]]\\\\\\\\\\\\\\\
3889\\\\\\\\\\\\\\\
3890if not fs.exists(\\\\\\\\\\\\\\\"/.tmp\\\\\\\\\\\\\\\") then\\\\\\\\\\\\\\\
3891 fs.makeDir(\\\\\\\\\\\\\\\"/.tmp\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3892end\\\\\\\\\\\\\\\
3893\\\\\\\\\\\\\\\
3894local h_kernel = fs.open(\\\\\\\\\\\\\\\"/.tmp/kernel\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"w\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3895local h_gui = fs.open(\\\\\\\\\\\\\\\"/.tmp/gui\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"w\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3896h_kernel.writeLine(temp_kernel)\\\\\\\\\\\\\\\
3897h_kernel.close()\\\\\\\\\\\\\\\
3898h_gui.writeLine(temp_gui)\\\\\\\\\\\\\\\
3899h_gui.close()\\\\\\\\\\\\\\\
3900\\\\\\\\\\\\\\\
3901os.version = function()\\\\\\\\\\\\\\\
3902 return \\\\\\\\\\\\\\\"Tesseract Bootstrap 1.0\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\
3903end\\\\\\\\\\\\\\\
3904\\\\\\\\\\\\\\\
3905os.loadAPI(\\\\\\\\\\\\\\\"/.tmp/kernel\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3906os.loadAPI(\\\\\\\\\\\\\\\"/.tmp/gui\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3907\\\\\\\\\\\\\\\
3908fs.delete(\\\\\\\\\\\\\\\"/.tmp/kernel\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3909fs.delete(\\\\\\\\\\\\\\\"/.tmp/gui\\\\\\\\\\\\\\\")\\\\\\\\\\\\\\\
3910\\\\\\\\\\\\\\\
3911gui.printAppSuccess(\\\\\\\\\\\\\\\"tesseract\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"bootstrap kernel loaded\\\\\\\\\\\\\\\")\\\\\\\"\\\",\\\
3912}\",\
3913 \"F:kernel.map\",\
3914 \"\\\"-- Darwin native API\\\\\\\
3915\\\\\\\
3916-- LOCALS\\\\\\\
3917\\\\\\\
3918-- declare bug check codes\\\\\\\
3919local tmp_kc = {}\\\\\\\
3920tmp_kc[0x0000] = \\\\\\\"UNDEFINED_EXCEPTION\\\\\\\"\\\\\\\
3921tmp_kc[0x0001] = \\\\\\\"KERNEL_INTEGRITY_VIOLATION\\\\\\\"\\\\\\\
3922tmp_kc[0x0002] = \\\\\\\"KERNEL_ASSEMBLY_NOT_ACCESSIBLE\\\\\\\"\\\\\\\
3923tmp_kc[0x0003] = \\\\\\\"FIRMWARE_VERSION_INCOMPATIBLE\\\\\\\"\\\\\\\
3924tmp_kc[0x0004] = \\\\\\\"ATTEMPTED_KERNEL_ENVIRONMENT_BYPASS\\\\\\\"\\\\\\\
3925tmp_kc[0x0005] = \\\\\\\"ATTEMPTED_KERNEL_STRUCT_MODIFICATION\\\\\\\"\\\\\\\
3926tmp_kc[0xFFFE] = \\\\\\\"DELIBERATELY_THROWN_EXCEPTION\\\\\\\"\\\\\\\
3927tmp_kc[0xFFFF] = \\\\\\\"UNHANDLED_USER_MODE_EXCEPTION\\\\\\\"\\\\\\\
3928\\\\\\\
3929-- handle the bug check codes\\\\\\\
3930local function handleBugCheckCode(code)\\\\\\\
3931 if code > 0xFFFFFFFF then\\\\\\\
3932 return \\\\\\\"0xFFFFFFFF\\\\\\\"\\\\\\\
3933 end\\\\\\\
3934 local h = \\\\\\\"0x00000000\\\\\\\"\\\\\\\
3935 local code_s = string.format(\\\\\\\"%X\\\\\\\", code)\\\\\\\
3936 return string.format(\\\\\\\"%s%s\\\\\\\", string.sub(h, 1, h:len() - code_s:len()), code_s)\\\\\\\
3937end\\\\\\\
3938\\\\\\\
3939local function getCodeID(c)\\\\\\\
3940 if code > 0xFFFFFFFF then\\\\\\\
3941 return tmp_kc[0x00000000]\\\\\\\
3942 end\\\\\\\
3943 return tmp_kc[c] or tmp_kc[0x00000000]\\\\\\\
3944end\\\\\\\
3945\\\\\\\
3946local function handleBootMessage(str)\\\\\\\
3947 local s1 = \\\\\\\" \\\\\\\"\\\\\\\
3948 local n1 = s1:len()\\\\\\\
3949 local n2 = str:len()\\\\\\\
3950 local s2 = string.sub(s1, 1, n1-n2)\\\\\\\
3951 return \\\\\\\" \\\\\\\"..str..s2..\\\\\\\" \\\\\\\"\\\\\\\
3952end\\\\\\\
3953\\\\\\\
3954-- GLOBALS\\\\\\\
3955\\\\\\\
3956-- declare log function\\\\\\\
3957__declare(\\\\\\\"log\\\\\\\", function(l)\\\\\\\
3958 if not fs.exists(\\\\\\\"/etc/darwin.log\\\\\\\") then\\\\\\\
3959 x = fs.open(\\\\\\\"/etc/darwin.log\\\\\\\", \\\\\\\"w\\\\\\\")\\\\\\\
3960 else\\\\\\\
3961 x = fs.open(\\\\\\\"/etc/darwin.log\\\\\\\", \\\\\\\"a\\\\\\\")\\\\\\\
3962 end\\\\\\\
3963 x.writeLine(tostring(os.day())..\\\\\\\"d:\\\\\\\"..textutils.formatTime(os.time(), true)..\\\\\\\" | \\\\\\\"..l)\\\\\\\
3964 x.close()\\\\\\\
3965end)\\\\\\\
3966\\\\\\\
3967-- declare bug check stub\\\\\\\
3968__declare(\\\\\\\"__kstop\\\\\\\", function(code, p1, p2, p3, p4)\\\\\\\
3969 os.pullEvent = os.pullEventRaw\\\\\\\
3970 local code_a = 0x00000000\\\\\\\
3971 if tmp_kc[code] ~= nil then\\\\\\\
3972 code_a = code\\\\\\\
3973 end\\\\\\\
3974 \\\\\\\
3975 t = string.format(\\\\\\\"KSTOP CALLED! %s %s %s %s %s %s\\\\\\\", handleBugCheckCode(code_a), tmp_kc[code_a], tostring(p1), tostring(p2), tostring(p3), tostring(p4))\\\\\\\
3976 log(t)\\\\\\\
3977 \\\\\\\
3978 if not __DEBUG then\\\\\\\
3979 os.reboot()\\\\\\\
3980 end\\\\\\\
3981 \\\\\\\
3982 term.setBackgroundColor(colors.blue)\\\\\\\
3983 term.setTextColor(colors.white)\\\\\\\
3984 term.clear()\\\\\\\
3985 term.setCursorPos(1,1)\\\\\\\
3986 \\\\\\\
3987 x = string.format([[\\\\\\\
3988The system has encountered an unrecoverable error.\\\\\\\
3989Your computer needs to be restarted.\\\\\\\
3990\\\\\\\
3991Please write down the following parameters\\\\\\\
3992and send them to the Darwin development team:\\\\\\\
3993\\\\\\\
3994[%s] %s\\\\\\\
3995 \\\\\\\
3996[1] %s\\\\\\\
3997[2] %s\\\\\\\
3998[3] %s\\\\\\\
3999[4] %s\\\\\\\
4000\\\\\\\
400115 seconds until reboot.\\\\\\\
4002]], handleBugCheckCode(code_a), tmp_kc[code_a], tostring(p1), tostring(p2), tostring(p3), tostring(p4))\\\\\\\
4003stdout(x..\\\\\\\"\\\\\\\\n\\\\\\\")\\\\\\\
4004sleep(15)\\\\\\\
4005os.reboot()\\\\\\\
4006end)\\\\\\\
4007\\\\\\\
4008-- declare executive\\\\\\\
4009__declare(\\\\\\\"run\\\\\\\", function(ap)\\\\\\\
4010 return os.run(getfenv(1), ap)\\\\\\\
4011end)\\\\\\\
4012\\\\\\\
4013-- declare device IDs\\\\\\\
4014local d = {}\\\\\\\
4015d.MONITOR = \\\\\\\"monitor\\\\\\\"\\\\\\\
4016d.FLOPPY = \\\\\\\"drive\\\\\\\"\\\\\\\
4017d.MODEM = \\\\\\\"modem\\\\\\\"\\\\\\\
4018d.PRINTER = \\\\\\\"printer\\\\\\\"\\\\\\\
4019__declare(\\\\\\\"DEVICE_ID\\\\\\\", __kstruct(d))\\\\\\\
4020\\\\\\\
4021-- declare FS access flags\\\\\\\
4022__declare_api(\\\\\\\"fs\\\\\\\", \\\\\\\"AF_READ\\\\\\\", \\\\\\\"r\\\\\\\")\\\\\\\
4023__declare_api(\\\\\\\"fs\\\\\\\", \\\\\\\"AF_WRITE\\\\\\\", \\\\\\\"w\\\\\\\")\\\\\\\
4024__declare_api(\\\\\\\"fs\\\\\\\", \\\\\\\"AF_APPEND\\\\\\\", \\\\\\\"a\\\\\\\")\\\\\\\
4025__declare_api(\\\\\\\"fs\\\\\\\", \\\\\\\"AF_READBINARY\\\\\\\", \\\\\\\"rb\\\\\\\")\\\\\\\
4026__declare_api(\\\\\\\"fs\\\\\\\", \\\\\\\"AF_WRITEBINARY\\\\\\\", \\\\\\\"wb\\\\\\\")\\\\\\\
4027__declare_api(\\\\\\\"fs\\\\\\\", \\\\\\\"AF_APPENDBINARY\\\\\\\", \\\\\\\"ab\\\\\\\")\\\\\\\
4028\\\\\\\
4029-- declare stream descriptors\\\\\\\
4030__declare(\\\\\\\"stdin\\\\\\\", read)\\\\\\\
4031__declare(\\\\\\\"stdout\\\\\\\", write)\\\\\\\
4032__declare(\\\\\\\"stderr\\\\\\\", printError)\\\\\\\
4033\\\\\\\
4034-- declare format descriptor\\\\\\\
4035__declare(\\\\\\\"printf\\\\\\\", function(...)\\\\\\\
4036stdout(string.format(...))\\\\\\\
4037end)\\\\\\\
4038\\\\\\\
4039-- declare kernel descriptor\\\\\\\
4040__declare(\\\\\\\"printk\\\\\\\", function(n, i)\\\\\\\
4041 local LOG_TYPES = {}\\\\\\\
4042 LOG_TYPES[0] = {colors.lightGray, \\\\\\\" i \\\\\\\"}\\\\\\\
4043 LOG_TYPES[1] = {colors.lime, \\\\\\\" v \\\\\\\"}\\\\\\\
4044 LOG_TYPES[2] = {colors.cyan, \\\\\\\" * \\\\\\\"}\\\\\\\
4045 LOG_TYPES[3] = {colors.orange, \\\\\\\" ! \\\\\\\"}\\\\\\\
4046 LOG_TYPES[4] = {colors.red, \\\\\\\"!!!\\\\\\\"}\\\\\\\
4047 if n > 4 then\\\\\\\
4048 n = 4\\\\\\\
4049 end\\\\\\\
4050 if __DEBUG then\\\\\\\
4051 term.setBackgroundColor(colors.black)\\\\\\\
4052 term.setTextColor(colors.gray)\\\\\\\
4053 stdout(\\\\\\\"[\\\\\\\")\\\\\\\
4054 term.setTextColor(LOG_TYPES[n][1])\\\\\\\
4055 stdout(LOG_TYPES[n][2])\\\\\\\
4056 term.setTextColor(colors.gray)\\\\\\\
4057 stdout(\\\\\\\"]\\\\\\\")\\\\\\\
4058 if n == 4 then\\\\\\\
4059 term.setTextColor(colors.red)\\\\\\\
4060 else\\\\\\\
4061 term.setTextColor(colors.lightGray) \\\\\\\
4062 end\\\\\\\
4063 stdout(\\\\\\\" \\\\\\\"..i..\\\\\\\"\\\\\\\\n\\\\\\\")\\\\\\\
4064 term.setTextColor(colors.white)\\\\\\\
4065 end\\\\\\\
4066 log(i)\\\\\\\
4067end)\\\\\\\
4068\\\\\\\
4069-- declare kernel reader\\\\\\\
4070__declare(\\\\\\\"kreadfile\\\\\\\", function(path)\\\\\\\
4071 local handle = fs.open(path, \\\\\\\"r\\\\\\\")\\\\\\\
4072 local content = handle.readAll()\\\\\\\
4073 handle.close()\\\\\\\
4074 return content\\\\\\\
4075end)\\\\\\\
4076\\\\\\\
4077-- declare temporary kernel-mode loader\\\\\\\
4078local function loadAssembly(path)\\\\\\\
4079 sleep(0.2)\\\\\\\
4080 if not fs.exists(path) or fs.isDir(path) then\\\\\\\
4081 printk(4, \\\\\\\"LOAD FAILED: \\\\\\\"..path)\\\\\\\
4082 return false\\\\\\\
4083 else\\\\\\\
4084 if dofile(path) then\\\\\\\
4085 ESI.UIColoredLine(18, handleBootMessage(\\\\\\\"Loaded: \\\\\\\"..path), colors.lightGray, colors.black)\\\\\\\
4086 return true\\\\\\\
4087 else\\\\\\\
4088 printk(4, \\\\\\\"LOAD FAILED: \\\\\\\"..path)\\\\\\\
4089 return false\\\\\\\
4090 end\\\\\\\
4091 end\\\\\\\
4092end\\\\\\\
4093\\\\\\\
4094__declare(\\\\\\\"__kload\\\\\\\", function(path)\\\\\\\
4095if not loadAssembly(path) then\\\\\\\
4096 return false, __kstop(0x00000002, path)\\\\\\\
4097else\\\\\\\
4098 return true, nil\\\\\\\
4099end\\\\\\\
4100end)\\\\\\\
4101\\\\\\\
4102-- declare finalizer\\\\\\\
4103__declare(\\\\\\\"__kfinalize\\\\\\\", function()\\\\\\\
4104__declare(\\\\\\\"__kload\\\\\\\", nil)\\\\\\\
4105__declare(\\\\\\\"__kread\\\\\\\", nil)\\\\\\\
4106__declare(\\\\\\\"__kfinalize\\\\\\\", nil)\\\\\\\
4107if __DEBUG then\\\\\\\
4108 __declare(\\\\\\\"__khandlecode\\\\\\\", handleBugCheckCode)\\\\\\\
4109 return\\\\\\\
4110end\\\\\\\
4111ESI.Finalize()\\\\\\\
4112__declare(\\\\\\\"__declare\\\\\\\", nil)\\\\\\\
4113__declare(\\\\\\\"__declare_api\\\\\\\", nil)\\\\\\\
4114end)\\\\\\\
4115\\\\\\\
4116-- return\\\\\\\
4117return 1\\\"\",\
4118 \"F:security.map\",\
4119 \"\\\"local oldReadOnly = _G[\\\\\\\"fs\\\\\\\"][\\\\\\\"isReadOnly\\\\\\\"]\\\\\\\
4120local oldMove = _G[\\\\\\\"fs\\\\\\\"][\\\\\\\"move\\\\\\\"]\\\\\\\
4121local oldDelete = _G[\\\\\\\"fs\\\\\\\"][\\\\\\\"delete\\\\\\\"]\\\\\\\
4122local oldHttpGet = _G[\\\\\\\"http\\\\\\\"][\\\\\\\"get\\\\\\\"]\\\\\\\
4123local oldError = _G[\\\\\\\"error\\\\\\\"]\\\\\\\
4124_G[\\\\\\\"fs\\\\\\\"][\\\\\\\"isReadOnly\\\\\\\"] = function(path)\\\\\\\
4125 local find1 = shell.resolve(path) or path\\\\\\\
4126 if string.find(find1, \\\\\\\"boot\\\\\\\") or string.find(find1, \\\\\\\"bin\\\\\\\") or string.find(find1, \\\\\\\"lib\\\\\\\") then\\\\\\\
4127 log(\\\\\\\"Attempt to access system files!\\\\\\\")\\\\\\\
4128 if __DEBUG then\\\\\\\
4129 log(\\\\\\\"Superuser access verified.\\\\\\\")\\\\\\\
4130 return false\\\\\\\
4131 else\\\\\\\
4132 log(\\\\\\\"Attempt blocked.\\\\\\\")\\\\\\\
4133 return true\\\\\\\
4134 end\\\\\\\
4135 elseif find1 == \\\\\\\"startup\\\\\\\" or find1 == \\\\\\\"/startup\\\\\\\" then\\\\\\\
4136 log(\\\\\\\"Attempt to access bootloader!\\\\\\\")\\\\\\\
4137 log(\\\\\\\"Attempt blocked.\\\\\\\")\\\\\\\
4138 return true\\\\\\\
4139 end \\\\\\\
4140 return oldReadOnly(path)\\\\\\\
4141end\\\\\\\
4142_G[\\\\\\\"fs\\\\\\\"][\\\\\\\"move\\\\\\\"] = function(path1, path2)\\\\\\\
4143 local find2 = shell.resolve(path1)\\\\\\\
4144 if string.find(find2, \\\\\\\"boot\\\\\\\") or string.find(find2, \\\\\\\"bin\\\\\\\") or string.find(find2, \\\\\\\"lib\\\\\\\") then\\\\\\\
4145 log(\\\\\\\"Attempt to access system files!\\\\\\\")\\\\\\\
4146 if __DEBUG then\\\\\\\
4147 log(\\\\\\\"Superuser access verified.\\\\\\\")\\\\\\\
4148 else\\\\\\\
4149 log(\\\\\\\"Attempt blocked.\\\\\\\")\\\\\\\
4150 return nil\\\\\\\
4151 end\\\\\\\
4152 elseif find2 == \\\\\\\"startup\\\\\\\" or find2 == \\\\\\\"/startup\\\\\\\" then\\\\\\\
4153 log(\\\\\\\"Attempt to access boot loader!\\\\\\\")\\\\\\\
4154 log(\\\\\\\"Attempt blocked.\\\\\\\")\\\\\\\
4155 return nil\\\\\\\
4156 end \\\\\\\
4157 return oldMove(path1, path2)\\\\\\\
4158end\\\\\\\
4159_G[\\\\\\\"fs\\\\\\\"][\\\\\\\"delete\\\\\\\"] = function(path)\\\\\\\
4160 local find3 = shell.resolve(path) or path\\\\\\\
4161 if string.find(find3, \\\\\\\"boot\\\\\\\") or string.find(find3, \\\\\\\"bin\\\\\\\") or string.find(find3, \\\\\\\"lib\\\\\\\") then\\\\\\\
4162 log(\\\\\\\"Attempt to access system files!\\\\\\\")\\\\\\\
4163 if __DEBUG then\\\\\\\
4164 log(\\\\\\\"Superuser access verified.\\\\\\\")\\\\\\\
4165 else\\\\\\\
4166 log(\\\\\\\"Attempt blocked.\\\\\\\")\\\\\\\
4167 return nil\\\\\\\
4168 end\\\\\\\
4169 elseif find3 == \\\\\\\"startup\\\\\\\" or find3 == \\\\\\\"/startup\\\\\\\" then\\\\\\\
4170 log(\\\\\\\"Attempt to access bootloader!\\\\\\\")\\\\\\\
4171 log(\\\\\\\"Attempt blocked.\\\\\\\")\\\\\\\
4172 return nil\\\\\\\
4173 end \\\\\\\
4174 return oldDelete(path)\\\\\\\
4175end\\\\\\\
4176_G[\\\\\\\"http\\\\\\\"][\\\\\\\"get\\\\\\\"] = function(url, headers)\\\\\\\
4177 log(\\\\\\\"Downloaded contents of \\\\\\\"..url)\\\\\\\
4178 return oldHttpGet(url, headers)\\\\\\\
4179end\\\"\",\
4180}",
4181 "D:etc",
4182 "{\
4183 \"F:darwin.log\",\
4184 \"\\\"3d:3:06 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
41853d:3:07 | Loaded system file: /lib/libuser.2.so\\\\\\\
41863d:3:07 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
41873d:3:07 | Darwin kernel loaded\\\\\\\
41883d:3:45 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
41893d:3:45 | Loaded system file: /lib/libuser.2.so\\\\\\\
41903d:3:45 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
41913d:3:45 | Darwin kernel loaded\\\\\\\
41923d:4:45 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
41933d:4:45 | Loaded system file: /lib/libuser.2.so\\\\\\\
41943d:4:46 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
41953d:4:46 | Darwin kernel loaded\\\\\\\
41963d:5:10 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
41973d:5:10 | Loaded system file: /lib/libuser.2.so\\\\\\\
41983d:5:11 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
41993d:5:11 | Darwin kernel loaded\\\\\\\
42003d:5:46 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
42013d:5:47 | Loaded system file: /lib/libuser.2.so\\\\\\\
42023d:5:47 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42033d:5:48 | Darwin kernel loaded\\\\\\\
42043d:9:37 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
42053d:9:37 | Loaded system file: /lib/libuser.2.so\\\\\\\
42063d:9:37 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42073d:9:38 | Darwin kernel loaded\\\\\\\
42083d:10:21 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
42093d:10:21 | Loaded system file: /lib/libuser.2.so\\\\\\\
42103d:10:21 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42113d:10:22 | Darwin kernel loaded\\\\\\\
42123d:11:06 | Downloaded contents of https://pastebin.com/raw/wFgCiYkY\\\\\\\
42135d:12:33 | Attempt to access system files!\\\\\\\
42145d:12:33 | Superuser access verified.\\\\\\\
42155d:12:33 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
42165d:12:33 | Loaded system file: /lib/libuser.2.so\\\\\\\
42175d:12:34 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42185d:12:34 | Darwin kernel loaded\\\\\\\
42195d:15:25 | Attempt to access system files!\\\\\\\
42205d:15:25 | Superuser access verified.\\\\\\\
42215d:15:25 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
42225d:15:25 | Loaded system file: /lib/libuser.2.so\\\\\\\
42235d:15:26 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42245d:15:26 | Darwin kernel loaded\\\\\\\
42251d:6:04 | Attempt to access system files!\\\\\\\
42261d:6:04 | Superuser access verified.\\\\\\\
42271d:6:04 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
42281d:6:05 | Loaded system file: /lib/libuser.2.so\\\\\\\
42291d:6:05 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42301d:6:06 | Darwin kernel loaded\\\\\\\
42312d:3:52 | Attempt to access system files!\\\\\\\
42322d:3:52 | Superuser access verified.\\\\\\\
42332d:3:52 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
42342d:3:52 | Loaded system file: /lib/libuser.2.so\\\\\\\
42352d:3:53 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42362d:3:53 | Darwin kernel loaded\\\\\\\
42372d:4:27 | Attempt to access system files!\\\\\\\
42382d:4:27 | Superuser access verified.\\\\\\\
42392d:4:27 | Loaded system file: /lib/libstdlua.2.so\\\\\\\
42402d:4:27 | Loaded system file: /lib/libuser.2.so\\\\\\\
42412d:4:27 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42422d:4:28 | Darwin kernel loaded\\\\\\\
42432d:12:34 | Darwin kernel loaded\\\\\\\
42442d:13:01 | Darwin kernel loaded\\\\\\\
42452d:13:25 | Darwin kernel loaded\\\\\\\
42462d:14:01 | Darwin kernel loaded\\\\\\\
42472d:15:32 | Darwin kernel loaded\\\\\\\
42482d:16:36 | Darwin kernel loaded\\\\\\\
42492d:19:15 | Attempt to access system files!\\\\\\\
42502d:19:15 | Superuser access verified.\\\\\\\
42512d:21:52 | Loaded system file: /lib/libdaemon.1.so\\\\\\\
42522d:21:53 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42532d:21:53 | Loaded system file: /lib/libsha256_anavrins.1.so\\\\\\\
42542d:21:53 | Loaded system file: /lib/libuser.2.so\\\\\\\
42552d:21:54 | Darwin kernel loaded\\\\\\\
42562d:23:04 | Loaded system file: /lib/libdaemon.1.so\\\\\\\
42572d:23:04 | Loaded system file: /lib/libgui_txui.1.so\\\\\\\
42582d:23:05 | Loaded system file: /lib/libsha256_anavrins.1.so\\\\\\\
42592d:23:05 | Loaded system file: /lib/libuser.2.so\\\\\\\
42603d:0:06 | Assembly loaded: /lib/libdaemon.1.so\\\\\\\
42613d:0:07 | Assembly loaded: /lib/libgui_txui.1.so\\\\\\\
42623d:0:07 | Assembly loaded: /lib/libsha256_anavrins.1.so\\\\\\\
42633d:0:07 | Assembly loaded: /lib/libuser.2.so\\\\\\\
42643d:0:48 | Loaded: /lib/libdaemon.1.so\\\\\\\
42653d:0:48 | Loaded: /lib/libgui_txui.1.so\\\\\\\
42663d:0:49 | Loaded: /lib/libsha256_anavrins.1.so\\\\\\\
42673d:0:49 | Loaded: /lib/libuser.2.so\\\\\\\
42683d:5:39 | Loaded: /lib/libdaemon.1.so\\\\\\\
42693d:5:39 | Loaded: /lib/libgui_txui.1.so\\\\\\\
42703d:5:40 | Loaded: /lib/libsha256_anavrins.1.so\\\\\\\
42713d:5:40 | Loaded: /lib/libuser.2.so\\\\\\\
42723d:6:01 | Loaded: /lib/libdaemon.1.so\\\\\\\
42733d:6:02 | Loaded: /lib/libgui_txui.1.so\\\\\\\
42743d:6:02 | Loaded: /lib/libsha256_anavrins.1.so\\\\\\\
42753d:6:02 | Loaded: /lib/libuser.2.so\\\\\\\
42764d:18:12 | Downloaded contents of https://pastebin.com/raw/bggiSgmc\\\\\\\
42775d:3:14 | Downloaded contents of https://pastebin.com/raw/ZGJGBJdg\\\\\\\
42785d:20:19 | Attempt to access system files!\\\\\\\
42795d:20:19 | Superuser access verified.\\\\\\\
42806d:11:06 | Attempt to access system files!\\\\\\\
42816d:11:06 | Superuser access verified.\\\\\\\
42826d:11:11 | Attempt to access system files!\\\\\\\
42836d:11:11 | Superuser access verified.\\\\\\\
42846d:11:27 | Attempt to access system files!\\\\\\\
42856d:11:27 | Superuser access verified.\\\\\\\
42866d:11:46 | Attempt to access system files!\\\\\\\
42876d:11:46 | Superuser access verified.\\\\\\\
42886d:12:21 | Attempt to access system files!\\\\\\\
42896d:12:21 | Superuser access verified.\\\\\\\
42906d:19:51 | Attempt to access system files!\\\\\\\
42916d:19:51 | Superuser access verified.\\\\\\\
42926d:19:56 | Attempt to access system files!\\\\\\\
42936d:19:56 | Superuser access verified.\\\"\",\
4294 \"F:process\",\
4295 \"\\\"\\\\\\\
4296-- Setup process switching\\\\\\\
4297local parentTerm = term.current()\\\\\\\
4298local w,h = parentTerm.getSize()\\\\\\\
4299\\\\\\\
4300local tProcesses = {}\\\\\\\
4301local nCurrentProcess = nil\\\\\\\
4302local nRunningProcess = nil\\\\\\\
4303local bShowMenu = false\\\\\\\
4304local bWindowsResized = false\\\\\\\
4305\\\\\\\
4306local function selectProcess( n )\\\\\\\
4307 if nCurrentProcess ~= n then\\\\\\\
4308 if nCurrentProcess then\\\\\\\
4309 local tOldProcess = tProcesses[ nCurrentProcess ]\\\\\\\
4310 tOldProcess.window.setVisible( false )\\\\\\\
4311 end\\\\\\\
4312 nCurrentProcess = n\\\\\\\
4313 if nCurrentProcess then\\\\\\\
4314 local tNewProcess = tProcesses[ nCurrentProcess ]\\\\\\\
4315 tNewProcess.window.setVisible( true )\\\\\\\
4316 tNewProcess.bInteracted = true\\\\\\\
4317 end\\\\\\\
4318 end\\\\\\\
4319end\\\\\\\
4320\\\\\\\
4321local function setProcessTitle( n, sTitle )\\\\\\\
4322 tProcesses[ n ].sTitle = sTitle\\\\\\\
4323end\\\\\\\
4324\\\\\\\
4325local function resumeProcess( nProcess, sEvent, ... )\\\\\\\
4326 local tProcess = tProcesses[ nProcess ]\\\\\\\
4327 local sFilter = tProcess.sFilter\\\\\\\
4328 if sFilter == nil or sFilter == sEvent or sEvent == \\\\\\\"terminate\\\\\\\" then\\\\\\\
4329 local nPreviousProcess = nRunningProcess\\\\\\\
4330 nRunningProcess = nProcess\\\\\\\
4331 term.redirect( tProcess.terminal )\\\\\\\
4332 local ok, result = coroutine.resume( tProcess.co, sEvent, ... )\\\\\\\
4333 tProcess.terminal = term.current()\\\\\\\
4334 if ok then\\\\\\\
4335 tProcess.sFilter = result\\\\\\\
4336 else\\\\\\\
4337 printError( result )\\\\\\\
4338 end\\\\\\\
4339 nRunningProcess = nPreviousProcess\\\\\\\
4340 end\\\\\\\
4341end\\\\\\\
4342\\\\\\\
4343local function launchProcess( tProgramEnv, sProgramPath, ... )\\\\\\\
4344 local tProgramArgs = table.pack( ... )\\\\\\\
4345 local nProcess = #tProcesses + 1\\\\\\\
4346 local tProcess = {}\\\\\\\
4347 tProcess.sTitle = fs.getName( sProgramPath )\\\\\\\
4348 if bShowMenu then\\\\\\\
4349 tProcess.window = window.create( parentTerm, 1, 2, w, h-1, false )\\\\\\\
4350 else\\\\\\\
4351 tProcess.window = window.create( parentTerm, 1, 1, w, h, false )\\\\\\\
4352 end\\\\\\\
4353 tProcess.co = coroutine.create( function()\\\\\\\
4354 os.run( tProgramEnv, sProgramPath, table.unpack( tProgramArgs, 1, tProgramArgs.n ) )\\\\\\\
4355 if not tProcess.bInteracted then\\\\\\\
4356 term.setCursorBlink( false )\\\\\\\
4357 print( \\\\\\\"Press any key to continue\\\\\\\" )\\\\\\\
4358 os.pullEvent( \\\\\\\"char\\\\\\\" )\\\\\\\
4359 end\\\\\\\
4360 end )\\\\\\\
4361 tProcess.sFilter = nil\\\\\\\
4362 tProcess.terminal = tProcess.window\\\\\\\
4363 tProcess.bInteracted = false\\\\\\\
4364 tProcesses[ nProcess ] = tProcess\\\\\\\
4365 resumeProcess( nProcess )\\\\\\\
4366 return nProcess\\\\\\\
4367end\\\\\\\
4368\\\\\\\
4369local function cullProcess( nProcess )\\\\\\\
4370 local tProcess = tProcesses[ nProcess ]\\\\\\\
4371 if coroutine.status( tProcess.co ) == \\\\\\\"dead\\\\\\\" then\\\\\\\
4372 if nCurrentProcess == nProcess then\\\\\\\
4373 selectProcess( nil )\\\\\\\
4374 end\\\\\\\
4375 table.remove( tProcesses, nProcess )\\\\\\\
4376 if nCurrentProcess == nil then\\\\\\\
4377 if nProcess > 1 then\\\\\\\
4378 selectProcess( nProcess - 1 )\\\\\\\
4379 elseif #tProcesses > 0 then\\\\\\\
4380 selectProcess( 1 )\\\\\\\
4381 end\\\\\\\
4382 end\\\\\\\
4383 return true\\\\\\\
4384 end\\\\\\\
4385 return false\\\\\\\
4386end\\\\\\\
4387\\\\\\\
4388local function cullProcesses()\\\\\\\
4389 local culled = false\\\\\\\
4390 for n=#tProcesses,1,-1 do\\\\\\\
4391 culled = culled or cullProcess( n )\\\\\\\
4392 end\\\\\\\
4393 return culled\\\\\\\
4394end\\\\\\\
4395\\\\\\\
4396-- Setup the main menu\\\\\\\
4397local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor\\\\\\\
4398if parentTerm.isColor() then\\\\\\\
4399 menuMainTextColor, menuMainBgColor = colors.yellow, colors.black\\\\\\\
4400 menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray\\\\\\\
4401else\\\\\\\
4402 menuMainTextColor, menuMainBgColor = colors.white, colors.black\\\\\\\
4403 menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray\\\\\\\
4404end\\\\\\\
4405\\\\\\\
4406local function redrawMenu()\\\\\\\
4407 if bShowMenu then\\\\\\\
4408 -- Draw menu\\\\\\\
4409 parentTerm.setCursorPos( 1, 1 )\\\\\\\
4410 parentTerm.setBackgroundColor( menuOtherBgColor )\\\\\\\
4411 parentTerm.clearLine()\\\\\\\
4412 for n=1,#tProcesses do\\\\\\\
4413 if n == nCurrentProcess then\\\\\\\
4414 parentTerm.setTextColor( menuMainTextColor )\\\\\\\
4415 parentTerm.setBackgroundColor( menuMainBgColor )\\\\\\\
4416 else\\\\\\\
4417 parentTerm.setTextColor( menuOtherTextColor )\\\\\\\
4418 parentTerm.setBackgroundColor( menuOtherBgColor )\\\\\\\
4419 end\\\\\\\
4420 parentTerm.write( \\\\\\\" \\\\\\\" .. tProcesses[n].sTitle .. \\\\\\\" \\\\\\\" )\\\\\\\
4421 end\\\\\\\
4422\\\\\\\
4423 -- Put the cursor back where it should be\\\\\\\
4424 local tProcess = tProcesses[ nCurrentProcess ]\\\\\\\
4425 if tProcess then\\\\\\\
4426 tProcess.window.restoreCursor()\\\\\\\
4427 end\\\\\\\
4428 end\\\\\\\
4429end\\\\\\\
4430\\\\\\\
4431local function resizeWindows()\\\\\\\
4432 local windowY, windowHeight\\\\\\\
4433 if bShowMenu then\\\\\\\
4434 windowY = 2\\\\\\\
4435 windowHeight = h-1\\\\\\\
4436 else\\\\\\\
4437 windowY = 1\\\\\\\
4438 windowHeight = h\\\\\\\
4439 end\\\\\\\
4440 for n=1,#tProcesses do\\\\\\\
4441 local tProcess = tProcesses[n]\\\\\\\
4442 local window = tProcess.window\\\\\\\
4443 local x,y = tProcess.window.getCursorPos()\\\\\\\
4444 if y > windowHeight then\\\\\\\
4445 tProcess.window.scroll( y - windowHeight )\\\\\\\
4446 tProcess.window.setCursorPos( x, windowHeight )\\\\\\\
4447 end\\\\\\\
4448 tProcess.window.reposition( 1, windowY, w, windowHeight )\\\\\\\
4449 end\\\\\\\
4450 bWindowsResized = true\\\\\\\
4451end\\\\\\\
4452\\\\\\\
4453local function setMenuVisible( bVis )\\\\\\\
4454 if bShowMenu ~= bVis then\\\\\\\
4455 bShowMenu = bVis\\\\\\\
4456 resizeWindows()\\\\\\\
4457 redrawMenu()\\\\\\\
4458 end\\\\\\\
4459end\\\\\\\
4460\\\\\\\
4461local process = {}\\\\\\\
4462\\\\\\\
4463function process.getFocus()\\\\\\\
4464 return nCurrentProcess\\\\\\\
4465end\\\\\\\
4466\\\\\\\
4467function process.setFocus( n )\\\\\\\
4468 if type( n ) ~= \\\\\\\"number\\\\\\\" then\\\\\\\
4469 error( \\\\\\\"bad argument #1 (expected number, got \\\\\\\" .. type( n ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
4470 end\\\\\\\
4471 if n >= 1 and n <= #tProcesses then\\\\\\\
4472 selectProcess( n )\\\\\\\
4473 redrawMenu()\\\\\\\
4474 return true\\\\\\\
4475 end\\\\\\\
4476 return false\\\\\\\
4477end\\\\\\\
4478\\\\\\\
4479function process.getTitle( n )\\\\\\\
4480 if type( n ) ~= \\\\\\\"number\\\\\\\" then\\\\\\\
4481 error( \\\\\\\"bad argument #1 (expected number, got \\\\\\\" .. type( n ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
4482 end\\\\\\\
4483 if n >= 1 and n <= #tProcesses then\\\\\\\
4484 return tProcesses[n].sTitle\\\\\\\
4485 end\\\\\\\
4486 return nil\\\\\\\
4487end\\\\\\\
4488\\\\\\\
4489function process.setTitle( n, sTitle )\\\\\\\
4490 if type( n ) ~= \\\\\\\"number\\\\\\\" then\\\\\\\
4491 error( \\\\\\\"bad argument #1 (expected number, got \\\\\\\" .. type( n ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
4492 end\\\\\\\
4493 if type( sTitle ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
4494 error( \\\\\\\"bad argument #2 (expected string, got \\\\\\\" .. type( sTitle ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
4495 end\\\\\\\
4496 if n >= 1 and n <= #tProcesses then\\\\\\\
4497 setProcessTitle( n, sTitle )\\\\\\\
4498 redrawMenu()\\\\\\\
4499 end\\\\\\\
4500end\\\\\\\
4501\\\\\\\
4502function process.getCurrent()\\\\\\\
4503 return nRunningProcess\\\\\\\
4504end\\\\\\\
4505\\\\\\\
4506function process.launch( tProgramEnv, sProgramPath, ... )\\\\\\\
4507 if type( tProgramEnv ) ~= \\\\\\\"table\\\\\\\" then\\\\\\\
4508 error( \\\\\\\"bad argument #1 (expected table, got \\\\\\\" .. type( tProgramEnv ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
4509 end\\\\\\\
4510 if type( sProgramPath ) ~= \\\\\\\"string\\\\\\\" then\\\\\\\
4511 error( \\\\\\\"bad argument #2 (expected string, got \\\\\\\" .. type( sProgramPath ) .. \\\\\\\")\\\\\\\", 2 )\\\\\\\
4512 end\\\\\\\
4513 local previousTerm = term.current()\\\\\\\
4514 setMenuVisible( (#tProcesses + 1) >= 2 )\\\\\\\
4515 local nResult = launchProcess( tProgramEnv, sProgramPath, ... )\\\\\\\
4516 redrawMenu()\\\\\\\
4517 term.redirect( previousTerm )\\\\\\\
4518 return nResult\\\\\\\
4519end\\\\\\\
4520\\\\\\\
4521function process.getCount()\\\\\\\
4522 return #tProcesses\\\\\\\
4523end\\\\\\\
4524\\\\\\\
4525-- Begin\\\\\\\
4526parentTerm.clear()\\\\\\\
4527setMenuVisible( false )\\\\\\\
4528selectProcess( launchProcess( {\\\\\\\
4529 [\\\\\\\"shell\\\\\\\"] = shell,\\\\\\\
4530 [\\\\\\\"process\\\\\\\"] = process,\\\\\\\
4531}, \\\\\\\"/bin/msh\\\\\\\" ) )\\\\\\\
4532redrawMenu()\\\\\\\
4533\\\\\\\
4534-- Run processes\\\\\\\
4535while #tProcesses > 0 do\\\\\\\
4536 -- Get the event\\\\\\\
4537 local tEventData = table.pack( os.pullEventRaw() )\\\\\\\
4538 local sEvent = tEventData[1]\\\\\\\
4539 if sEvent == \\\\\\\"term_resize\\\\\\\" then\\\\\\\
4540 -- Resize event\\\\\\\
4541 w,h = parentTerm.getSize()\\\\\\\
4542 resizeWindows()\\\\\\\
4543 redrawMenu()\\\\\\\
4544\\\\\\\
4545 elseif sEvent == \\\\\\\"char\\\\\\\" or sEvent == \\\\\\\"key\\\\\\\" or sEvent == \\\\\\\"key_up\\\\\\\" or sEvent == \\\\\\\"paste\\\\\\\" or sEvent == \\\\\\\"terminate\\\\\\\" then\\\\\\\
4546 -- Keyboard event\\\\\\\
4547 -- Passthrough to current process\\\\\\\
4548 resumeProcess( nCurrentProcess, table.unpack( tEventData, 1, tEventData.n ) )\\\\\\\
4549 if cullProcess( nCurrentProcess ) then\\\\\\\
4550 setMenuVisible( #tProcesses >= 2 )\\\\\\\
4551 redrawMenu()\\\\\\\
4552 end\\\\\\\
4553\\\\\\\
4554 elseif sEvent == \\\\\\\"mouse_click\\\\\\\" then\\\\\\\
4555 -- Click event\\\\\\\
4556 local button, x, y = tEventData[2], tEventData[3], tEventData[4]\\\\\\\
4557 if bShowMenu and y == 1 then\\\\\\\
4558 -- Switch process\\\\\\\
4559 local tabStart = 1\\\\\\\
4560 for n=1,#tProcesses do\\\\\\\
4561 local tabEnd = tabStart + string.len( tProcesses[n].sTitle ) + 1\\\\\\\
4562 if x >= tabStart and x <= tabEnd then\\\\\\\
4563 selectProcess( n )\\\\\\\
4564 redrawMenu()\\\\\\\
4565 break\\\\\\\
4566 end\\\\\\\
4567 tabStart = tabEnd + 1\\\\\\\
4568 end\\\\\\\
4569 else\\\\\\\
4570 -- Passthrough to current process\\\\\\\
4571 resumeProcess( nCurrentProcess, sEvent, button, x, (bShowMenu and y-1) or y )\\\\\\\
4572 if cullProcess( nCurrentProcess ) then\\\\\\\
4573 setMenuVisible( #tProcesses >= 2 )\\\\\\\
4574 redrawMenu()\\\\\\\
4575 end\\\\\\\
4576 end\\\\\\\
4577\\\\\\\
4578 elseif sEvent == \\\\\\\"mouse_drag\\\\\\\" or sEvent == \\\\\\\"mouse_up\\\\\\\" or sEvent == \\\\\\\"mouse_scroll\\\\\\\" then\\\\\\\
4579 -- Other mouse event\\\\\\\
4580 local p1, x, y = tEventData[2], tEventData[3], tEventData[4]\\\\\\\
4581 if not (bShowMenu and y == 1) then\\\\\\\
4582 -- Passthrough to current process\\\\\\\
4583 resumeProcess( nCurrentProcess, sEvent, p1, x, (bShowMenu and y-1) or y )\\\\\\\
4584 if cullProcess( nCurrentProcess ) then\\\\\\\
4585 setMenuVisible( #tProcesses >= 2 )\\\\\\\
4586 redrawMenu()\\\\\\\
4587 end\\\\\\\
4588 end\\\\\\\
4589\\\\\\\
4590 else\\\\\\\
4591 -- Other event\\\\\\\
4592 -- Passthrough to all processes\\\\\\\
4593 local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event\\\\\\\
4594 for n=1,nLimit do\\\\\\\
4595 resumeProcess( n, table.unpack( tEventData, 1, tEventData.n ) )\\\\\\\
4596 end\\\\\\\
4597 if cullProcesses() then\\\\\\\
4598 setMenuVisible( #tProcesses >= 2 )\\\\\\\
4599 redrawMenu()\\\\\\\
4600 end\\\\\\\
4601 end\\\\\\\
4602\\\\\\\
4603 if bWindowsResized then\\\\\\\
4604 -- Pass term_resize to all processes\\\\\\\
4605 local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event\\\\\\\
4606 for n=1,nLimit do\\\\\\\
4607 resumeProcess( n, \\\\\\\"term_resize\\\\\\\" )\\\\\\\
4608 end\\\\\\\
4609 bWindowsResized = false\\\\\\\
4610 if cullProcesses() then\\\\\\\
4611 setMenuVisible( #tProcesses >= 2 )\\\\\\\
4612 redrawMenu()\\\\\\\
4613 end\\\\\\\
4614 end\\\\\\\
4615end\\\\\\\
4616\\\\\\\
4617-- Shutdown\\\\\\\
4618term.redirect( parentTerm )\\\"\",\
4619 \"D:resources\",\
4620 \"{\\\
4621 \\\"F:dialog_box.img\\\",\\\
4622 \\\"\\\\\\\"\\\\\\\\\\\\\\\
4623\\\\\\\\\\\\\\\
4624\\\\\\\\\\\\\\\
4625\\\\\\\\\\\\\\\
4626\\\\\\\\\\\\\\\
4627 000000000000000000000000000000000000000000000\\\\\\\\\\\\\\\
4628 0000000000000000000000000000000000000000000007\\\\\\\\\\\\\\\
4629 0000000000000000000000000000000000000000000007\\\\\\\\\\\\\\\
4630 0000000000000000000000000000000000000000000007\\\\\\\\\\\\\\\
4631 0777777777777777777777777777777777777777777707\\\\\\\\\\\\\\\
4632 0777777777777777777777777777777777777777777707\\\\\\\\\\\\\\\
4633 0777777777777777777777777777777777777777777707\\\\\\\\\\\\\\\
4634 0000000000000000000000000000000000000000000007\\\\\\\\\\\\\\\
4635 777777777777777777777777777777777777777777777\\\\\\\"\\\",\\\
4636}\",\
4637}",
4638 "D:lib",
4639 "{\
4640 \"F:libdaemon.1.so\",\
4641 \"\\\"local libcode = [[\\\\\\\
4642--a stateless iterator for use in for loops.\\\\\\\
4643local function fIter (t, i)\\\\\\\
4644 i = not i and #t or (i - 1)\\\\\\\
4645 if i>0 then\\\\\\\
4646 return i, t[i]\\\\\\\
4647 end\\\\\\\
4648end\\\\\\\
4649 \\\\\\\
4650--a table that stores all running daemons when we add a new value we first create a coroutine using the fFunc passed\\\\\\\
4651local tBackground = setmetatable({},{\\\\\\\
4652 __newindex = function(t, k, v)\\\\\\\
4653 v.cRoutine=coroutine.create(v[1])\\\\\\\
4654 rawset(t, k, v)\\\\\\\
4655 end;\\\\\\\
4656})\\\\\\\
4657 \\\\\\\
4658--starts a new daemon\\\\\\\
4659 \\\\\\\
4660--fFunc = function that runs in background\\\\\\\
4661--fError = function ran if fFunc ever ends for any reason\\\\\\\
4662 \\\\\\\
4663--returns identifier for new daemon\\\\\\\
4664\\\\\\\
4665function add(fFunc, fError)\\\\\\\
4666 tBackground[#tBackground + 1] = {fFunc, fError=fError}\\\\\\\
4667 return tBackground[#tBackground]\\\\\\\
4668end\\\\\\\
4669 \\\\\\\
4670--removes a running daemon\\\\\\\
4671--internally this sets a flag telling the system to remove this daemon next time it loops through\\\\\\\
4672--cRoutine = daemon to remove\\\\\\\
4673\\\\\\\
4674function rem(cRoutine)\\\\\\\
4675 cRoutine.sFilter=\\\\\\\"Daemon_internal_remove\\\\\\\"\\\\\\\
4676end\\\\\\\
4677 \\\\\\\
4678--returns identifiers for all running daemons\\\\\\\
4679function getBackground()\\\\\\\
4680 return tBackground\\\\\\\
4681end\\\\\\\
4682 \\\\\\\
4683--internal variable, determines what level of depth we are in the daemon\\\\\\\
4684local bPullMeta = false\\\\\\\
4685 \\\\\\\
4686 \\\\\\\
4687--replacing the native os.pullEventRaw to function\\\\\\\
4688__declare_api(\\\\\\\"os\\\\\\\", \\\\\\\"pullEventRaw\\\\\\\", function(sEvent)\\\\\\\
4689 local tData\\\\\\\
4690 \\\\\\\
4691 if bPullMeta then\\\\\\\
4692 return coroutine.yield(sEvent)\\\\\\\
4693 else\\\\\\\
4694 repeat\\\\\\\
4695 bPullMeta = true\\\\\\\
4696 tData = {coroutine.yield()}\\\\\\\
4697 \\\\\\\
4698 for iIndex, cRoutine in fIter, tBackground do --\\\\\\\
4699 if cRoutine.sFilter==tData[1] or not cRoutine.sFilter then\\\\\\\
4700 local bOk, sInnerEvent = coroutine.resume(cRoutine.cRoutine, unpack(tData))\\\\\\\
4701 if bOk then\\\\\\\
4702 cRoutine.sFilter = sInnerEvent\\\\\\\
4703 else\\\\\\\
4704 table.remove(tBackground, iIndex)\\\\\\\
4705 if cRoutine.fError then\\\\\\\
4706 cRoutine.fError(sInnerEvent, cRoutine)\\\\\\\
4707 end\\\\\\\
4708 end\\\\\\\
4709 elseif cRoutine.sFilter==\\\\\\\"Daemon_internal_remove\\\\\\\" then\\\\\\\
4710 table.remove(tBackground, iIndex)\\\\\\\
4711 end\\\\\\\
4712 end\\\\\\\
4713 bPullMeta = false\\\\\\\
4714 until tData[1] == sEvent or not sEvent\\\\\\\
4715 return unpack(tData)\\\\\\\
4716 end\\\\\\\
4717end)\\\\\\\
4718]]\\\\\\\
4719\\\\\\\
4720persist(\\\\\\\"daemon\\\\\\\", libcode)\\\\\\\
4721\\\\\\\
4722return 1\\\"\",\
4723 \"F:libgui_txui.1.so\",\
4724 \"\\\"local libcode = [[\\\\\\\
4725-- --\\\\\\\
4726-- txUI - ComputerCraft User Interface Library\\\\\\\
4727-- rel\\\\\\\
4728-- tuogex\\\\\\\
4729-- --\\\\\\\
4730\\\\\\\
4731-- --\\\\\\\
4732-- Controller @static\\\\\\\
4733-- Holds the windows of the program and handles events\\\\\\\
4734-- --\\\\\\\
4735Controller = {}\\\\\\\
4736Controller.prototype = {\\\\\\\
4737\\\\009--vars\\\\\\\
4738\\\\009components = {};\\\\\\\
4739\\\\009windows = {};\\\\\\\
4740\\\\009termSize = {};\\\\\\\
4741\\\\009spaceColor = colors.white;\\\\\\\
4742\\\\009style = {};\\\\\\\
4743\\\\009useNative = true;\\\\\\\
4744\\\\009multiWindow = false;\\\\\\\
4745\\\\009oldTerm = {};\\\\\\\
4746\\\\009--functions\\\\\\\
4747\\\\009drawAll = function(self)\\\\\\\
4748\\\\009\\\\009local w, h = term.getSize()\\\\\\\
4749\\\\009\\\\009Utils:drawRect(1, 1, w, h, self.spaceColor)\\\\\\\
4750\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4751\\\\009\\\\009\\\\009if (val.visible) then\\\\\\\
4752\\\\009\\\\009\\\\009\\\\009val:draw()\\\\\\\
4753\\\\009\\\\009\\\\009end\\\\\\\
4754\\\\009\\\\009end\\\\\\\
4755\\\\009\\\\009local drawQueue = {}\\\\\\\
4756\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4757\\\\009\\\\009\\\\009if (val.visible) then\\\\\\\
4758\\\\009\\\\009\\\\009\\\\009table.insert(drawQueue, 1, val)\\\\\\\
4759\\\\009\\\\009\\\\009end\\\\\\\
4760\\\\009\\\\009end\\\\\\\
4761\\\\009\\\\009for key, val in pairs(drawQueue) do\\\\\\\
4762\\\\009\\\\009\\\\009val:draw()\\\\\\\
4763\\\\009\\\\009end\\\\\\\
4764\\\\009end;\\\\\\\
4765\\\\009appUpdate = function(self, eventTbl) end;\\\\\\\
4766\\\\009startUpdateCycle = function(self)\\\\\\\
4767\\\\009\\\\009Controller.termSize = term.getSize()\\\\\\\
4768\\\\009\\\\009if (self.useNative) then\\\\\\\
4769\\\\009\\\\009\\\\009Controller.oldTerm = term.current()\\\\\\\
4770\\\\009\\\\009\\\\009term.redirect(term.native())\\\\\\\
4771\\\\009\\\\009end\\\\\\\
4772\\\\009\\\\009local handleEvent = function()\\\\\\\
4773\\\\009\\\\009\\\\009local event\\\\\\\
4774\\\\009\\\\009\\\\009repeat\\\\\\\
4775\\\\009\\\\009\\\\009\\\\009event = {os.pullEventRaw()}\\\\\\\
4776\\\\009\\\\009\\\\009until(event[1] ~= \\\\\\\"timer\\\\\\\")\\\\\\\
4777\\\\009\\\\009\\\\009if (event[1] == \\\\\\\"terminate\\\\\\\") then\\\\\\\
4778\\\\009\\\\009\\\\009\\\\009self:terminate()\\\\\\\
4779\\\\009\\\\009\\\\009elseif (event[1] == \\\\\\\"mouse_click\\\\\\\" or event[1] == \\\\\\\"monitor_touch\\\\\\\") then\\\\\\\
4780\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4781\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:click(event[3], event[4], event[2])) then\\\\\\\
4782\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4783\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4784\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4785\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4786\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and Utils:inBounds(val.x, val.y, val.w, val.h, event[3], event[4]) and tostring(self.windows[1]) ~= tostring(val)) then\\\\\\\
4787\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009table.remove(self.windows, key)\\\\\\\
4788\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009table.insert(self.windows, 1, val)\\\\\\\
4789\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4790\\\\009\\\\009\\\\009\\\\009\\\\009elseif (val.visible and Utils:inBounds(val.x, val.y, val.w, val.h, event[3], event[4]) and tostring(self.windows[1]) == tostring(val)) then\\\\\\\
4791\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4792\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4793\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4794\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4795\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and Utils:inBounds(val.x, val.y, val.w, val.h, event[3], event[4]) and tostring(self.windows[1]) == tostring(val) and val:click(event[3], event[4], event[2])) then\\\\\\\
4796\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4797\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4798\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4799\\\\009\\\\009\\\\009elseif (event[1] == \\\\\\\"mouse_scroll\\\\\\\") then\\\\\\\
4800\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4801\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:scroll(event[2])) then\\\\\\\
4802\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4803\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4804\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4805\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4806\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:scroll(event[2])) then\\\\\\\
4807\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4808\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4809\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4810\\\\009\\\\009\\\\009elseif (event[1] == \\\\\\\"mouse_drag\\\\\\\") then\\\\\\\
4811\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4812\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:drag(event[3], event[4], event[2])) then\\\\\\\
4813\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4814\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4815\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4816\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4817\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:drag(event[3], event[4], event[2])) then\\\\\\\
4818\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4819\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4820\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4821\\\\009\\\\009\\\\009elseif (event[1] == \\\\\\\"char\\\\\\\") then\\\\\\\
4822\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4823\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:char(event[2])) then\\\\\\\
4824\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4825\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4826\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4827\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4828\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:char(event[2])) then\\\\\\\
4829\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4830\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4831\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4832\\\\009\\\\009\\\\009elseif (event[1] == \\\\\\\"key\\\\\\\") then\\\\\\\
4833\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4834\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:key(event[2])) then\\\\\\\
4835\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4836\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4837\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4838\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4839\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:key(event[2])) then\\\\\\\
4840\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4841\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4842\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4843\\\\009\\\\009\\\\009else\\\\\\\
4844\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4845\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:event(event)) then\\\\\\\
4846\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4847\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4848\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4849\\\\009\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4850\\\\009\\\\009\\\\009\\\\009\\\\009if (val.visible and val:event(event)) then\\\\\\\
4851\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009break\\\\\\\
4852\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4853\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4854\\\\009\\\\009\\\\009end\\\\\\\
4855\\\\009\\\\009\\\\009return event\\\\\\\
4856\\\\009\\\\009end\\\\\\\
4857\\\\009\\\\009while (true) do\\\\\\\
4858\\\\009\\\\009\\\\009if (#self.windows == 0 and #self.components == 0) then\\\\\\\
4859\\\\009\\\\009\\\\009\\\\009self:exit()\\\\\\\
4860\\\\009\\\\009\\\\009end\\\\\\\
4861\\\\009\\\\009\\\\009self:drawAll()\\\\\\\
4862\\\\009\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4863\\\\009\\\\009\\\\009\\\\009if (val.visible) then\\\\\\\
4864\\\\009\\\\009\\\\009\\\\009\\\\009val:update()\\\\\\\
4865\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4866\\\\009\\\\009\\\\009end\\\\\\\
4867\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4868\\\\009\\\\009\\\\009\\\\009if (val.visible) then\\\\\\\
4869\\\\009\\\\009\\\\009\\\\009\\\\009val:update()\\\\\\\
4870\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4871\\\\009\\\\009\\\\009end\\\\\\\
4872\\\\009\\\\009\\\\009local eventTbl = handleEvent()\\\\\\\
4873\\\\009\\\\009\\\\009self:appUpdate(eventTbl);\\\\\\\
4874\\\\009\\\\009\\\\009--remove components marked for removal\\\\\\\
4875\\\\009\\\\009\\\\009local removed = {}\\\\\\\
4876\\\\009\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4877\\\\009\\\\009\\\\009\\\\009if (val.removed) then\\\\\\\
4878\\\\009\\\\009\\\\009\\\\009\\\\009table.insert(removed, key)\\\\\\\
4879\\\\009\\\\009\\\\009\\\\009else\\\\\\\
4880\\\\009\\\\009\\\\009\\\\009\\\\009val:update()\\\\\\\
4881\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4882\\\\009\\\\009\\\\009end\\\\\\\
4883\\\\009\\\\009\\\\009for key, val in pairs(removed) do\\\\\\\
4884\\\\009\\\\009\\\\009\\\\009self.components[val] = nil\\\\\\\
4885\\\\009\\\\009\\\\009end\\\\\\\
4886\\\\009\\\\009\\\\009--close windows marked for close\\\\\\\
4887\\\\009\\\\009\\\\009local closed = {}\\\\\\\
4888\\\\009\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4889\\\\009\\\\009\\\\009\\\\009if (val.closed) then\\\\\\\
4890\\\\009\\\\009\\\\009\\\\009\\\\009table.insert(closed, key)\\\\\\\
4891\\\\009\\\\009\\\\009\\\\009end\\\\\\\
4892\\\\009\\\\009\\\\009end\\\\\\\
4893\\\\009\\\\009\\\\009for key, val in pairs(closed) do\\\\\\\
4894\\\\009\\\\009\\\\009\\\\009self.windows[val] = nil\\\\\\\
4895\\\\009\\\\009\\\\009end\\\\\\\
4896\\\\009\\\\009end\\\\\\\
4897\\\\009end;\\\\\\\
4898\\\\009setVisibleWindow = function(self, windowTbl)\\\\\\\
4899\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4900\\\\009\\\\009\\\\009local wasVisible = val.visible\\\\\\\
4901\\\\009\\\\009\\\\009val.visible = (tostring(val) == tostring(windowTbl) or self.multiWindow)\\\\\\\
4902\\\\009\\\\009\\\\009if (not wasVisible and val.visible) then\\\\\\\
4903\\\\009\\\\009\\\\009\\\\009val:onView()\\\\\\\
4904\\\\009\\\\009\\\\009end\\\\\\\
4905\\\\009\\\\009\\\\009if (wasVisible and not val.visible) then\\\\\\\
4906\\\\009\\\\009\\\\009\\\\009val:onHide()\\\\\\\
4907\\\\009\\\\009\\\\009end\\\\\\\
4908\\\\009\\\\009end\\\\\\\
4909\\\\009end;\\\\\\\
4910\\\\009addWindow = function(self, windowTbl)\\\\\\\
4911\\\\009\\\\009windowTbl.closed = false\\\\\\\
4912\\\\009\\\\009windowTbl.visible = self.multiWindow\\\\\\\
4913\\\\009\\\\009table.insert(self.windows, windowTbl)\\\\\\\
4914\\\\009\\\\009if (#self.windows == 1) then\\\\\\\
4915\\\\009\\\\009\\\\009self:setVisibleWindow(windowTbl)\\\\\\\
4916\\\\009\\\\009end\\\\\\\
4917\\\\009end;\\\\\\\
4918\\\\009closeWindow = function(self, windowTbl)\\\\\\\
4919\\\\009\\\\009for key, val in pairs(self.windows) do\\\\\\\
4920\\\\009\\\\009\\\\009if (val == windowTbl) then\\\\\\\
4921\\\\009\\\\009\\\\009\\\\009val.closed = true\\\\\\\
4922\\\\009\\\\009\\\\009end\\\\\\\
4923\\\\009\\\\009end\\\\\\\
4924\\\\009end;\\\\\\\
4925\\\\009addComponent = function(self, componentTbl)\\\\\\\
4926\\\\009\\\\009componentTbl.parent = self\\\\\\\
4927\\\\009\\\\009componentTbl.parent.x = 1\\\\\\\
4928\\\\009\\\\009componentTbl.parent.y = 1\\\\\\\
4929\\\\009\\\\009componentTbl.parent.w = self.termSize[1]\\\\\\\
4930\\\\009\\\\009componentTbl.parent.h = self.termSize[2]\\\\\\\
4931\\\\009\\\\009componentTbl.removed = false\\\\\\\
4932\\\\009\\\\009table.insert(self.components, componentTbl)\\\\\\\
4933\\\\009end;\\\\\\\
4934\\\\009removeComponent = function(self, componentTbl)\\\\\\\
4935\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
4936\\\\009\\\\009\\\\009if (val == componentTbl) then\\\\\\\
4937\\\\009\\\\009\\\\009\\\\009val.removed = true\\\\\\\
4938\\\\009\\\\009\\\\009end\\\\\\\
4939\\\\009\\\\009end\\\\\\\
4940\\\\009end;\\\\\\\
4941\\\\009terminate = function(self)\\\\\\\
4942\\\\009\\\\009self:exit()\\\\\\\
4943\\\\009end;\\\\\\\
4944\\\\009exit = function(self)\\\\\\\
4945\\\\009\\\\009if (self.useNative) then\\\\\\\
4946\\\\009\\\\009\\\\009term.redirect(self.oldTerm)\\\\\\\
4947\\\\009\\\\009end\\\\\\\
4948\\\\009\\\\009term.setBackgroundColor(colors.black)\\\\\\\
4949\\\\009\\\\009term.clear()\\\\\\\
4950\\\\009\\\\009term.setCursorPos(1, 1)\\\\\\\
4951\\\\009\\\\009error()\\\\\\\
4952\\\\009end;\\\\\\\
4953\\\\009cloneComponent = function(self, obj, copied)\\\\\\\
4954\\\\009\\\\009if type(obj) ~= 'table' then\\\\\\\
4955\\\\009\\\\009\\\\009return obj\\\\\\\
4956\\\\009\\\\009end\\\\\\\
4957\\\\009\\\\009if copied and copied[obj] then\\\\\\\
4958\\\\009\\\\009\\\\009return copied[obj]\\\\\\\
4959\\\\009\\\\009end\\\\\\\
4960\\\\009\\\\009local c = copied or {}\\\\\\\
4961\\\\009\\\\009local res = setmetatable({}, getmetatable(obj))\\\\\\\
4962\\\\009\\\\009c[obj] = res\\\\\\\
4963\\\\009\\\\009for k, v in pairs(obj) do\\\\\\\
4964\\\\009\\\\009\\\\009res[self:cloneComponent(k, c)] = self:cloneComponent(v, c)\\\\\\\
4965\\\\009\\\\009end\\\\\\\
4966\\\\009\\\\009return res\\\\\\\
4967\\\\009end;\\\\\\\
4968\\\\009inheritComponent = function(self, obj, newTbl)\\\\\\\
4969\\\\009\\\\009local oldComponent = self:cloneComponent(obj)\\\\\\\
4970\\\\009\\\\009for k, v in pairs(newTbl) do\\\\\\\
4971\\\\009\\\\009\\\\009oldComponent[k] = v\\\\\\\
4972\\\\009\\\\009end \\\\\\\
4973\\\\009\\\\009return oldComponent\\\\\\\
4974\\\\009end;\\\\\\\
4975\\\\009setDefaultStyle = function(self, styleTbl)\\\\\\\
4976\\\\009\\\\009self.style = styleTbl\\\\\\\
4977\\\\009end;\\\\\\\
4978}\\\\\\\
4979Controller.mt = {\\\\\\\
4980\\\\009__index = function (table, key)\\\\\\\
4981\\\\009\\\\009return Controller.prototype[key]\\\\\\\
4982\\\\009end;\\\\\\\
4983}\\\\\\\
4984setmetatable(Controller, Controller.mt)\\\\\\\
4985\\\\\\\
4986-- --\\\\\\\
4987-- Utils @static\\\\\\\
4988-- Utilities to aid in UI design\\\\\\\
4989-- --\\\\\\\
4990Utils = {}\\\\\\\
4991Utils.prototype = {\\\\\\\
4992\\\\009drawRect = function(self, x, y, w, h, color)\\\\\\\
4993\\\\009\\\\009term.setBackgroundColor(color)\\\\\\\
4994\\\\009\\\\009for pY = y, h - 1 + y, 1 do\\\\\\\
4995\\\\009\\\\009\\\\009term.setCursorPos(x, pY)\\\\\\\
4996\\\\009\\\\009\\\\009for pX = x, w - 1 + x, 1 do\\\\\\\
4997\\\\009\\\\009\\\\009\\\\009term.write(\\\\\\\" \\\\\\\")\\\\\\\
4998\\\\009\\\\009\\\\009end\\\\\\\
4999\\\\009\\\\009end\\\\\\\
5000\\\\009end;\\\\\\\
5001\\\\009alignText = function(self, alignment, textLength, x, w)\\\\\\\
5002\\\\009\\\\009if (alignment == \\\\\\\"left\\\\\\\") then\\\\\\\
5003\\\\009\\\\009\\\\009return x\\\\\\\
5004\\\\009\\\\009elseif (alignment == \\\\\\\"center\\\\\\\") then\\\\\\\
5005\\\\009\\\\009\\\\009return x + ((w - textLength) / 2)\\\\\\\
5006\\\\009\\\\009elseif (alignment == \\\\\\\"right\\\\\\\") then\\\\\\\
5007\\\\009\\\\009\\\\009return x + (w - textLength)\\\\\\\
5008\\\\009\\\\009end\\\\\\\
5009\\\\009end;\\\\\\\
5010\\\\009limitText = function(self, text, limit, tail)\\\\\\\
5011\\\\009\\\\009if (string.len(text) > limit) then\\\\\\\
5012\\\\009\\\\009\\\\009return string.sub(text, 0, limit - string.len(tail)) .. tail\\\\\\\
5013\\\\009\\\\009else\\\\\\\
5014\\\\009\\\\009\\\\009return text\\\\\\\
5015\\\\009\\\\009end\\\\\\\
5016\\\\009end;\\\\\\\
5017\\\\009wrapText = function(self, text, limit)\\\\\\\
5018\\\\009\\\\009local index = 0\\\\\\\
5019\\\\009\\\\009return text:gsub(\\\\\\\"(%C?)\\\\\\\", function (w)\\\\\\\
5020\\\\009\\\\009\\\\009index = index + 1\\\\\\\
5021\\\\009\\\\009\\\\009return w .. (index % limit == 0 and \\\\\\\"\\\\\\\\n\\\\\\\" or \\\\\\\"\\\\\\\")\\\\\\\
5022\\\\009\\\\009end)\\\\\\\
5023\\\\009end;\\\\\\\
5024\\\\009splitText = function(self, str, pat)\\\\\\\
5025\\\\009\\\\009local t = {}\\\\\\\
5026\\\\009\\\\009local fpat = \\\\\\\"(.-)\\\\\\\" .. pat\\\\\\\
5027\\\\009\\\\009local last_end = 1\\\\\\\
5028\\\\009\\\\009local s, e, cap = str:find(fpat, 1)\\\\\\\
5029\\\\009\\\\009while s do\\\\\\\
5030\\\\009\\\\009\\\\009if (s ~= 1 or cap ~= \\\\\\\"\\\\\\\") then\\\\\\\
5031\\\\009\\\\009\\\\009\\\\009table.insert(t,cap)\\\\\\\
5032\\\\009\\\\009\\\\009end\\\\\\\
5033\\\\009\\\\009\\\\009last_end = e + 1\\\\\\\
5034\\\\009\\\\009\\\\009s, e, cap = str:find(fpat, last_end)\\\\\\\
5035\\\\009\\\\009end\\\\\\\
5036\\\\009\\\\009if (last_end <= #str) then\\\\\\\
5037\\\\009\\\\009\\\\009cap = str:sub(last_end)\\\\\\\
5038\\\\009\\\\009\\\\009table.insert(t, cap)\\\\\\\
5039\\\\009\\\\009end\\\\\\\
5040\\\\009\\\\009return t\\\\\\\
5041\\\\009end;\\\\\\\
5042\\\\009inBounds = function(self, boundX, boundY, boundW, boundH, checkX, checkY)\\\\\\\
5043\\\\009\\\\009local xInBound = (checkX >= boundX) and (checkX <= boundX + boundW - 1)\\\\\\\
5044\\\\009\\\\009local yInBound = (checkY >= boundY) and (checkY <= boundY + boundH - 1)\\\\\\\
5045\\\\009\\\\009return xInBound and yInBound\\\\\\\
5046\\\\009end;\\\\\\\
5047}\\\\\\\
5048Utils.mt = {\\\\\\\
5049\\\\009__index = function(table, key)\\\\\\\
5050\\\\009\\\\009return Utils.prototype[key]\\\\\\\
5051\\\\009end;\\\\\\\
5052}\\\\\\\
5053setmetatable(Utils, Utils.mt)\\\\\\\
5054\\\\\\\
5055-- --\\\\\\\
5056-- Style\\\\\\\
5057-- Contains default styles for components and windows\\\\\\\
5058-- --\\\\\\\
5059Style = {}\\\\\\\
5060Style.prototype = {\\\\\\\
5061\\\\009Window = {};\\\\\\\
5062\\\\009Component = {};\\\\\\\
5063\\\\009Panel = {};\\\\\\\
5064\\\\009Button = {};\\\\\\\
5065\\\\009Label = {};\\\\\\\
5066\\\\009TextField = {};\\\\\\\
5067\\\\009List = {};\\\\\\\
5068\\\\009CheckBox = {};\\\\\\\
5069\\\\009ProgressBar = {};\\\\\\\
5070}\\\\\\\
5071Style.mt = {\\\\\\\
5072\\\\009__index = function (table, key)\\\\\\\
5073\\\\009\\\\009return Style.prototype[key]\\\\\\\
5074\\\\009end;\\\\\\\
5075}\\\\\\\
5076function Style:new(styleTbl)\\\\\\\
5077\\\\009setmetatable(styleTbl, Style.mt)\\\\\\\
5078\\\\009return styleTbl\\\\\\\
5079end\\\\\\\
5080\\\\\\\
5081-- --\\\\\\\
5082-- Window\\\\\\\
5083-- Pretty self explainatory\\\\\\\
5084-- --\\\\\\\
5085Window = {}\\\\\\\
5086Window.prototype = {\\\\\\\
5087\\\\009-- vars\\\\\\\
5088\\\\009bgColor = colors.lightGray;\\\\\\\
5089\\\\009tlColor = colors.gray;\\\\\\\
5090\\\\009activeTlColor = colors.blue;\\\\\\\
5091\\\\009components = {};\\\\\\\
5092\\\\009titleLabel = {};\\\\\\\
5093\\\\009z = 0;\\\\\\\
5094\\\\009x = 1;\\\\\\\
5095\\\\009y = 1;\\\\\\\
5096\\\\009h = 1;\\\\\\\
5097\\\\009w = 1;\\\\\\\
5098\\\\009draggable = false;\\\\\\\
5099\\\\009lastClick = {};\\\\\\\
5100\\\\009hasShadow = false;\\\\\\\
5101\\\\009shadowColor = colors.black;\\\\\\\
5102\\\\009visible = false;\\\\\\\
5103\\\\009closed = false;\\\\\\\
5104\\\\009--functions\\\\\\\
5105\\\\009draw = function(self)\\\\\\\
5106\\\\009\\\\009--draw shadow\\\\\\\
5107\\\\009\\\\009if (self.hasShadow) then\\\\\\\
5108\\\\009\\\\009\\\\009Utils:drawRect(self.x + 1, self.y + 1, self.w, self.h, self.shadowColor)\\\\\\\
5109\\\\009\\\\009end\\\\\\\
5110\\\\009\\\\009--drawPane\\\\\\\
5111\\\\009\\\\009Utils:drawRect(self.x, self.y, self.w, self.h, self.bgColor)\\\\\\\
5112\\\\009\\\\009--drawTitle\\\\\\\
5113\\\\009\\\\009term.setBackgroundColor((self:isActive() and Controller.multiWindow) and self.activeTlColor or self.tlColor)\\\\\\\
5114\\\\009\\\\009term.setCursorPos(self.x, self.y)\\\\\\\
5115\\\\009\\\\009for pX = self.x, self.w + self.x - 1, 1 do\\\\\\\
5116\\\\009\\\\009\\\\009term.write(\\\\\\\" \\\\\\\")\\\\\\\
5117\\\\009\\\\009end\\\\\\\
5118\\\\009\\\\009if (self.titleLabel.draw ~= nil) then\\\\\\\
5119\\\\009\\\\009\\\\009self.titleLabel:draw()\\\\\\\
5120\\\\009\\\\009end\\\\\\\
5121\\\\009\\\\009--draw components\\\\\\\
5122\\\\009\\\\009self:drawComponents()\\\\\\\
5123\\\\009end;\\\\\\\
5124\\\\009drawComponents = function(self)\\\\\\\
5125\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5126\\\\009\\\\009\\\\009if (val.visible) then\\\\\\\
5127\\\\009\\\\009\\\\009\\\\009val:draw()\\\\\\\
5128\\\\009\\\\009\\\\009end\\\\\\\
5129\\\\009\\\\009end\\\\\\\
5130\\\\009end;\\\\\\\
5131\\\\009setTitleLabel = function(self, newLabel)\\\\\\\
5132\\\\009\\\\009newLabel.parent = self\\\\\\\
5133\\\\009\\\\009setmetatable(newLabel, Label.tlmt)\\\\\\\
5134\\\\009\\\\009self.titleLabel = newLabel\\\\\\\
5135\\\\009end;\\\\\\\
5136\\\\009addComponent = function(self, componentTbl)\\\\\\\
5137\\\\009\\\\009componentTbl.parent = self\\\\\\\
5138\\\\009\\\\009componentTbl.removed = false\\\\\\\
5139\\\\009\\\\009table.insert(self.components, componentTbl)\\\\\\\
5140\\\\009end;\\\\\\\
5141\\\\009removeComponent = function(self, componentTbl)\\\\\\\
5142\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5143\\\\009\\\\009\\\\009if (val == componentTbl) then\\\\\\\
5144\\\\009\\\\009\\\\009\\\\009val.removed = true\\\\\\\
5145\\\\009\\\\009\\\\009end\\\\\\\
5146\\\\009\\\\009end\\\\\\\
5147\\\\009end;\\\\\\\
5148\\\\009close = function(self)\\\\\\\
5149\\\\009\\\\009Controller:closeWindow(self)\\\\\\\
5150\\\\009end;\\\\\\\
5151\\\\009click = function(self, x, y)\\\\\\\
5152\\\\009\\\\009if (self.draggable and ((x >= self.x) and (x <= (self.x + self.w - 1)) and (y >= self.y) and (y <= self.y))) then\\\\\\\
5153\\\\009\\\\009\\\\009self.lastClick.x = x\\\\\\\
5154\\\\009\\\\009\\\\009self.lastClick.y = y\\\\\\\
5155\\\\009\\\\009else\\\\\\\
5156\\\\009\\\\009\\\\009self.lastClick.x = nil\\\\\\\
5157\\\\009\\\\009\\\\009self.lastClick.y = nil\\\\\\\
5158\\\\009\\\\009end\\\\\\\
5159\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5160\\\\009\\\\009\\\\009val:click(x, y)\\\\\\\
5161\\\\009\\\\009end\\\\\\\
5162\\\\009\\\\009return (self.draggable and ((x >= self.x) and (x <= (self.x + self.w - 1)) and (y >= self.y) and (y <= self.y)))\\\\\\\
5163\\\\009end;\\\\\\\
5164\\\\009key = function(self, keyCode)\\\\\\\
5165\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5166\\\\009\\\\009\\\\009val:key(keyCode)\\\\\\\
5167\\\\009\\\\009end\\\\\\\
5168\\\\009end;\\\\\\\
5169\\\\009char = function(self, char)\\\\\\\
5170\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5171\\\\009\\\\009\\\\009val:char(char)\\\\\\\
5172\\\\009\\\\009end\\\\\\\
5173\\\\009end;\\\\\\\
5174\\\\009scroll = function(self, direction)\\\\\\\
5175\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5176\\\\009\\\\009\\\\009val:scroll(direction)\\\\\\\
5177\\\\009\\\\009end\\\\\\\
5178\\\\009end;\\\\\\\
5179\\\\009drag = function(self, x, y)\\\\\\\
5180\\\\009\\\\009if (self.draggable and self.lastClick.x ~= nil) then\\\\\\\
5181\\\\009\\\\009\\\\009self.x = self.x + x - self.lastClick.x\\\\\\\
5182\\\\009\\\\009\\\\009self.y = self.y + y - self.lastClick.y\\\\\\\
5183\\\\009\\\\009\\\\009self.lastClick.x = x\\\\\\\
5184\\\\009\\\\009\\\\009self.lastClick.y = y\\\\\\\
5185\\\\009\\\\009end\\\\\\\
5186\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5187\\\\009\\\\009\\\\009val:drag(x, y)\\\\\\\
5188\\\\009\\\\009end\\\\\\\
5189\\\\009end;\\\\\\\
5190\\\\009event = function(self, eventTbl)\\\\\\\
5191\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5192\\\\009\\\\009\\\\009val:event(eventTbl)\\\\\\\
5193\\\\009\\\\009end\\\\\\\
5194\\\\009end;\\\\\\\
5195\\\\009onView = function(self)\\\\\\\
5196\\\\009end;\\\\\\\
5197\\\\009onHide = function(self)\\\\\\\
5198\\\\009end;\\\\\\\
5199\\\\009update = function(self)\\\\\\\
5200\\\\009\\\\009local removed = {}\\\\\\\
5201\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5202\\\\009\\\\009\\\\009if (val.removed) then\\\\\\\
5203\\\\009\\\\009\\\\009\\\\009table.insert(removed, key)\\\\\\\
5204\\\\009\\\\009\\\\009else\\\\\\\
5205\\\\009\\\\009\\\\009\\\\009val:update()\\\\\\\
5206\\\\009\\\\009\\\\009end\\\\\\\
5207\\\\009\\\\009end\\\\\\\
5208\\\\009\\\\009for key, val in pairs(removed) do\\\\\\\
5209\\\\009\\\\009\\\\009self.components[val] = nil\\\\\\\
5210\\\\009\\\\009end\\\\\\\
5211\\\\009end;\\\\\\\
5212\\\\009isActive = function(self)\\\\\\\
5213\\\\009\\\\009return Controller.windows[1] == self\\\\\\\
5214\\\\009end;\\\\\\\
5215}\\\\\\\
5216Window.mt = {\\\\\\\
5217\\\\009__index = function (table, key)\\\\\\\
5218\\\\009\\\\009if (Controller.style.Window[key] ~= nil) then\\\\\\\
5219\\\\009\\\\009\\\\009return Controller.style.Window[key]\\\\\\\
5220\\\\009\\\\009else\\\\\\\
5221\\\\009\\\\009\\\\009return Window.prototype[key]\\\\\\\
5222\\\\009\\\\009end\\\\\\\
5223\\\\009end;\\\\\\\
5224}\\\\\\\
5225function Window:new(windowTbl)\\\\\\\
5226\\\\009setmetatable(windowTbl, Window.mt)\\\\\\\
5227\\\\009windowTbl.components = {}\\\\\\\
5228\\\\009return windowTbl\\\\\\\
5229end\\\\\\\
5230\\\\\\\
5231-- --\\\\\\\
5232-- Component @abstract\\\\\\\
5233-- Abstract class used to represent components in a window\\\\\\\
5234-- --\\\\\\\
5235Component = {}\\\\\\\
5236Component.prototype = {\\\\\\\
5237\\\\009--vars\\\\\\\
5238\\\\009x = 1;\\\\\\\
5239\\\\009y = 1;\\\\\\\
5240\\\\009h = 1;\\\\\\\
5241\\\\009w = 1;\\\\\\\
5242\\\\009z = 0;\\\\\\\
5243\\\\009parent = {};\\\\\\\
5244\\\\009removed = false;\\\\\\\
5245\\\\009visible = true;\\\\\\\
5246\\\\009--functions\\\\\\\
5247\\\\009draw = function(self) end;\\\\\\\
5248\\\\009click = function(self, x, y, button) return false end;\\\\\\\
5249\\\\009key = function(self, keyCode) return false end;\\\\\\\
5250\\\\009char = function(self, char) return false end;\\\\\\\
5251\\\\009scroll = function(self, direction) return false end;\\\\\\\
5252\\\\009drag = function(self, x, y, button) return false end;\\\\\\\
5253\\\\009event = function(self, eventTbl) return false end;\\\\\\\
5254\\\\009update = function(self) return false end;\\\\\\\
5255\\\\009termX = function(self) return self.x + self.parent.x - 1 end;\\\\\\\
5256\\\\009termY = function(self) return self.y + self.parent.y - 1 end;\\\\\\\
5257\\\\009setPos = function(self, x, y)\\\\\\\
5258\\\\009\\\\009self.x = x;\\\\\\\
5259\\\\009\\\\009self.y = y;\\\\\\\
5260\\\\009end;\\\\\\\
5261\\\\009setSize = function(self, w, h)\\\\\\\
5262\\\\009\\\\009self.w = w;\\\\\\\
5263\\\\009\\\\009self.h = h;\\\\\\\
5264\\\\009end;\\\\\\\
5265}\\\\\\\
5266\\\\\\\
5267-- --\\\\\\\
5268-- Panel\\\\\\\
5269-- Pretty self explainatory\\\\\\\
5270-- --\\\\\\\
5271Panel = {}\\\\\\\
5272Panel.prototype = {\\\\\\\
5273\\\\009-- vars\\\\\\\
5274\\\\009bgColor = colors.lightGray;\\\\\\\
5275\\\\009components = {};\\\\\\\
5276\\\\009z = 0;\\\\\\\
5277\\\\009x = 1;\\\\\\\
5278\\\\009y = 1;\\\\\\\
5279\\\\009h = 1;\\\\\\\
5280\\\\009w = 1;\\\\\\\
5281\\\\009--functions\\\\\\\
5282\\\\009draw = function(self)\\\\\\\
5283\\\\009\\\\009--drawPane\\\\\\\
5284\\\\009\\\\009Utils:drawRect(self.x, self.y, self.w, self.h, self.bgColor)\\\\\\\
5285\\\\009\\\\009--draw components\\\\\\\
5286\\\\009\\\\009self:drawComponents()\\\\\\\
5287\\\\009end;\\\\\\\
5288\\\\009drawComponents = function(self)\\\\\\\
5289\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5290\\\\009\\\\009\\\\009val:draw()\\\\\\\
5291\\\\009\\\\009end\\\\\\\
5292\\\\009end;\\\\\\\
5293\\\\009addComponent = function(self, componentTbl)\\\\\\\
5294\\\\009\\\\009componentTbl.parent = self\\\\\\\
5295\\\\009\\\\009componentTbl.removed = false\\\\\\\
5296\\\\009\\\\009table.insert(self.components, componentTbl)\\\\\\\
5297\\\\009end;\\\\\\\
5298\\\\009removeComponent = function(self, componentTbl)\\\\\\\
5299\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5300\\\\009\\\\009\\\\009if (val == componentTbl) then\\\\\\\
5301\\\\009\\\\009\\\\009\\\\009val.removed = true\\\\\\\
5302\\\\009\\\\009\\\\009end\\\\\\\
5303\\\\009\\\\009end\\\\\\\
5304\\\\009end;\\\\\\\
5305\\\\009close = function(self)\\\\\\\
5306\\\\009\\\\009Controller:closeWindow(self)\\\\\\\
5307\\\\009end;\\\\\\\
5308\\\\009click = function(self, x, y)\\\\\\\
5309\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5310\\\\009\\\\009\\\\009val:click(x, y)\\\\\\\
5311\\\\009\\\\009end\\\\\\\
5312\\\\009end;\\\\\\\
5313\\\\009key = function(self, keyCode)\\\\\\\
5314\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5315\\\\009\\\\009\\\\009val:key(keyCode)\\\\\\\
5316\\\\009\\\\009end\\\\\\\
5317\\\\009end;\\\\\\\
5318\\\\009char = function(self, char)\\\\\\\
5319\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5320\\\\009\\\\009\\\\009val:char(char)\\\\\\\
5321\\\\009\\\\009end\\\\\\\
5322\\\\009end;\\\\\\\
5323\\\\009scroll = function(self, direction)\\\\\\\
5324\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5325\\\\009\\\\009\\\\009val:scroll(direction)\\\\\\\
5326\\\\009\\\\009end\\\\\\\
5327\\\\009end;\\\\\\\
5328\\\\009drag = function(self, x, y)\\\\\\\
5329\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5330\\\\009\\\\009\\\\009val:drag(x, y)\\\\\\\
5331\\\\009\\\\009end\\\\\\\
5332\\\\009end;\\\\\\\
5333\\\\009event = function(self, eventTbl)\\\\\\\
5334\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5335\\\\009\\\\009\\\\009val:event(eventTbl)\\\\\\\
5336\\\\009\\\\009end\\\\\\\
5337\\\\009end;\\\\\\\
5338\\\\009update = function(self)\\\\\\\
5339\\\\009\\\\009local removed = {}\\\\\\\
5340\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5341\\\\009\\\\009\\\\009if (val.removed) then\\\\\\\
5342\\\\009\\\\009\\\\009\\\\009table.insert(removed, key)\\\\\\\
5343\\\\009\\\\009\\\\009else\\\\\\\
5344\\\\009\\\\009\\\\009\\\\009val:update()\\\\\\\
5345\\\\009\\\\009\\\\009end\\\\\\\
5346\\\\009\\\\009end\\\\\\\
5347\\\\009\\\\009for key, val in pairs(removed) do\\\\\\\
5348\\\\009\\\\009\\\\009self.components[val] = nil\\\\\\\
5349\\\\009\\\\009end\\\\\\\
5350\\\\009end;\\\\\\\
5351}\\\\\\\
5352Panel.mt = {\\\\\\\
5353\\\\009__index = function (table, key)\\\\\\\
5354\\\\009\\\\009if (Controller.style.Panel[key] ~= nil) then\\\\\\\
5355\\\\009\\\\009\\\\009return Controller.style.Panel[key]\\\\\\\
5356\\\\009\\\\009elseif (Panel.prototype[key] ~= nil) then\\\\\\\
5357\\\\009\\\\009\\\\009return Panel.prototype[key]\\\\\\\
5358\\\\009\\\\009else\\\\\\\
5359\\\\009\\\\009\\\\009return Component.prototype[key]\\\\\\\
5360\\\\009\\\\009end\\\\\\\
5361\\\\009end;\\\\\\\
5362}\\\\\\\
5363function Panel:new(panelTbl)\\\\\\\
5364\\\\009setmetatable(panelTbl, Panel.mt)\\\\\\\
5365\\\\009panelTbl.components = {}\\\\\\\
5366\\\\009return panelTbl\\\\\\\
5367end\\\\\\\
5368\\\\\\\
5369-- --\\\\\\\
5370-- Button extends Component\\\\\\\
5371-- A component that you can click\\\\\\\
5372-- --\\\\\\\
5373Button = {}\\\\\\\
5374Button.prototype = {\\\\\\\
5375\\\\009--vars\\\\\\\
5376\\\\009h = 3;\\\\\\\
5377\\\\009w = 16;\\\\\\\
5378\\\\009bgColor = colors.lightBlue;\\\\\\\
5379\\\\009textColor = colors.white;\\\\\\\
5380\\\\009activeColor = colors.blue;\\\\\\\
5381\\\\009activeTextColor = colors.white;\\\\\\\
5382\\\\009active = false;\\\\\\\
5383\\\\009text = \\\\\\\"txUI Button\\\\\\\";\\\\\\\
5384\\\\009textAlign = \\\\\\\"center\\\\\\\";\\\\\\\
5385\\\\009vertCenter = true;\\\\\\\
5386\\\\009--functions\\\\\\\
5387\\\\009action = function(self) end;\\\\\\\
5388\\\\009draw = function(self)\\\\\\\
5389\\\\009\\\\009Utils:drawRect(self:termX(), self:termY(), self.w, self.h, (function(self) if (self.active) then return self.activeColor else return self.bgColor end end)(self))\\\\\\\
5390\\\\009\\\\009term.setTextColor((function(self) if (self.active) then return self.activeTextColor else return self.textColor end end)(self))\\\\\\\
5391\\\\009\\\\009local lines = #Utils:splitText(self.text, \\\\\\\"\\\\\\\\n\\\\\\\")\\\\\\\
5392\\\\009\\\\009for k, v in ipairs(Utils:splitText(self.text, \\\\\\\"\\\\\\\\n\\\\\\\")) do\\\\\\\
5393\\\\009\\\\009\\\\009term.setCursorPos(Utils:alignText(self.textAlign, string.len(v), self:termX(), self.w), self:termY() + k - 1 + (self.vertCenter and ((self.h - lines) / 2) or 0))\\\\\\\
5394\\\\009\\\\009\\\\009term.write(v)\\\\\\\
5395\\\\009\\\\009end\\\\\\\
5396\\\\009end;\\\\\\\
5397\\\\009click = function (self, x, y)\\\\\\\
5398\\\\009\\\\009if ((x >= self:termX()) and (x <= (self:termX() + self.w - 1)) and (y >= self:termY()) and (y <= (self:termY() + self.h - 1))) then\\\\\\\
5399\\\\009\\\\009\\\\009self.active = true\\\\\\\
5400\\\\009\\\\009\\\\009self:action()\\\\\\\
5401\\\\009\\\\009else\\\\\\\
5402\\\\009\\\\009\\\\009self.active = false\\\\\\\
5403\\\\009\\\\009end\\\\\\\
5404\\\\009end;\\\\\\\
5405\\\\009update = function(self) return false end;\\\\\\\
5406}\\\\\\\
5407Button.mt = {\\\\\\\
5408\\\\009__index = function (table, key)\\\\\\\
5409\\\\009\\\\009if (Controller.style.Button[key] ~= nil) then\\\\\\\
5410\\\\009\\\\009\\\\009return Controller.style.Button[key]\\\\\\\
5411\\\\009\\\\009elseif (Button.prototype[key] ~= nil) then\\\\\\\
5412\\\\009\\\\009\\\\009return Button.prototype[key]\\\\\\\
5413\\\\009\\\\009else\\\\\\\
5414\\\\009\\\\009\\\\009return Component.prototype[key]\\\\\\\
5415\\\\009\\\\009end\\\\\\\
5416\\\\009end;\\\\\\\
5417}\\\\\\\
5418function Button:new(buttonTbl)\\\\\\\
5419\\\\009if (buttonTbl == nil) then\\\\\\\
5420\\\\009\\\\009buttonTbl = self\\\\\\\
5421\\\\009end\\\\\\\
5422\\\\009setmetatable(buttonTbl, Button.mt)\\\\\\\
5423\\\\009return buttonTbl\\\\\\\
5424end\\\\\\\
5425\\\\\\\
5426-- --\\\\\\\
5427-- Label extends Component\\\\\\\
5428-- A component that displays text\\\\\\\
5429-- --\\\\\\\
5430Label = {}\\\\\\\
5431Label.prototype = {\\\\\\\
5432\\\\009--vars\\\\\\\
5433\\\\009h = 1;\\\\\\\
5434\\\\009w = 16;\\\\\\\
5435\\\\009bgColor = colors.white;\\\\\\\
5436\\\\009textColor = colors.black;\\\\\\\
5437\\\\009text = \\\\\\\"txUI Label\\\\\\\";\\\\\\\
5438\\\\009textAlign = \\\\\\\"center\\\\\\\";\\\\\\\
5439\\\\009vertCenter = true;\\\\\\\
5440\\\\009--functions\\\\\\\
5441\\\\009draw = function(self)\\\\\\\
5442\\\\009\\\\009Utils:drawRect(self:termX(), self:termY(), self.w, self.h, self.bgColor)\\\\\\\
5443\\\\009\\\\009term.setBackgroundColor(self.bgColor)\\\\\\\
5444\\\\009\\\\009term.setTextColor(self.textColor)\\\\\\\
5445\\\\009\\\\009local lines = #Utils:splitText(self.text, \\\\\\\"\\\\\\\\n\\\\\\\")\\\\\\\
5446\\\\009\\\\009for k, v in ipairs(Utils:splitText(self.text, \\\\\\\"\\\\\\\\n\\\\\\\")) do\\\\\\\
5447\\\\009\\\\009\\\\009term.setCursorPos(Utils:alignText(self.textAlign, string.len(v), self:termX(), self.w), self:termY() + k - 1 + (self.vertCenter and ((self.h - lines) / 2) or 0))\\\\\\\
5448\\\\009\\\\009\\\\009term.write(v)\\\\\\\
5449\\\\009\\\\009end\\\\\\\
5450\\\\009end;\\\\\\\
5451\\\\009update = function(self) return false end;\\\\\\\
5452}\\\\\\\
5453Label.mt = {\\\\\\\
5454\\\\009__index = function (table, key)\\\\\\\
5455\\\\009\\\\009if (Label.prototype[key] ~= nil) then\\\\\\\
5456\\\\009\\\\009\\\\009return Label.prototype[key]\\\\\\\
5457\\\\009\\\\009else\\\\\\\
5458\\\\009\\\\009\\\\009return Component.prototype[key]\\\\\\\
5459\\\\009\\\\009end\\\\\\\
5460\\\\009end;\\\\\\\
5461}\\\\\\\
5462Label.tlmt = {\\\\\\\
5463\\\\009__index = function (table, key)\\\\\\\
5464\\\\009\\\\009if (key == \\\\\\\"w\\\\\\\") then\\\\\\\
5465\\\\009\\\\009\\\\009return table.parent.w\\\\\\\
5466\\\\009\\\\009elseif (key == \\\\\\\"bgColor\\\\\\\") then\\\\\\\
5467\\\\009\\\\009\\\\009return table.parent.tlColor\\\\\\\
5468\\\\009\\\\009elseif (Label.prototype[key] ~= nil) then\\\\\\\
5469\\\\009\\\\009\\\\009return Label.prototype[key]\\\\\\\
5470\\\\009\\\\009else\\\\\\\
5471\\\\009\\\\009\\\\009return Component.prototype[key]\\\\\\\
5472\\\\009\\\\009end\\\\\\\
5473\\\\009end;\\\\\\\
5474}\\\\\\\
5475function Label:new(labelTbl)\\\\\\\
5476\\\\009if (labelTbl == nil) then\\\\\\\
5477\\\\009\\\\009labelTbl = self\\\\\\\
5478\\\\009end\\\\\\\
5479\\\\009setmetatable(labelTbl, Label.mt)\\\\\\\
5480\\\\009return labelTbl\\\\\\\
5481end\\\\\\\
5482\\\\\\\
5483-- --\\\\\\\
5484-- TextField extends Component\\\\\\\
5485-- A component that allows for text input\\\\\\\
5486-- --\\\\\\\
5487TextField = {}\\\\\\\
5488TextField.prototype = {\\\\\\\
5489\\\\009--vars\\\\\\\
5490\\\\009h = 1;\\\\\\\
5491\\\\009w = 16;\\\\\\\
5492\\\\009bgColor = colors.white;\\\\\\\
5493\\\\009textColor = colors.black;\\\\\\\
5494\\\\009placeholderColor = colors.lightGray;\\\\\\\
5495\\\\009placeholder = \\\\\\\"txUI TextField\\\\\\\";\\\\\\\
5496\\\\009text = \\\\\\\"\\\\\\\";\\\\\\\
5497\\\\009textAlign = \\\\\\\"left\\\\\\\";\\\\\\\
5498\\\\009textMask = \\\\\\\"\\\\\\\";\\\\\\\
5499\\\\009active = false;\\\\\\\
5500\\\\009cursorPos = 0;\\\\\\\
5501\\\\009displayOffset = 0;\\\\\\\
5502\\\\009--functions\\\\\\\
5503\\\\009draw = function(self)\\\\\\\
5504\\\\009\\\\009Utils:drawRect(self:termX(), self:termY(), self.w, self.h, self.bgColor)\\\\\\\
5505\\\\009\\\\009term.setBackgroundColor(self.bgColor)\\\\\\\
5506\\\\009\\\\009if (self.active or string.len(self.text) ~= 0) then\\\\\\\
5507\\\\009\\\\009\\\\009local toWrite = string.sub(self.text, self.displayOffset + 1, self.displayOffset + self.w)\\\\\\\
5508\\\\009\\\\009\\\\009if (string.len(self.textMask) ~= 0) then\\\\\\\
5509\\\\009\\\\009\\\\009\\\\009toWrite = string.gsub(toWrite, \\\\\\\"%C\\\\\\\", self.textMask)\\\\\\\
5510\\\\009\\\\009\\\\009end\\\\\\\
5511\\\\009\\\\009\\\\009term.setCursorPos(Utils:alignText(self.textAlign, string.len(toWrite), self:termX(), self.w), self:termY() + (self.h / 2))\\\\\\\
5512\\\\009\\\\009\\\\009term.setTextColor(self.textColor)\\\\\\\
5513\\\\009\\\\009\\\\009term.write(toWrite)\\\\\\\
5514\\\\009\\\\009else\\\\\\\
5515\\\\009\\\\009\\\\009local toWrite = string.sub(self.placeholder, self.displayOffset + 1)\\\\\\\
5516\\\\009\\\\009\\\\009term.setCursorPos(Utils:alignText(self.textAlign, string.len(toWrite), self:termX(), self.w), self:termY() + (self.h / 2))\\\\\\\
5517\\\\009\\\\009\\\\009term.setTextColor(self.placeholderColor)\\\\\\\
5518\\\\009\\\\009\\\\009term.write(toWrite)\\\\\\\
5519\\\\009\\\\009end\\\\\\\
5520\\\\009\\\\009term.setCursorBlink(self.active)\\\\\\\
5521\\\\009\\\\009if (self.active) then\\\\\\\
5522\\\\009\\\\009\\\\009term.setCursorPos(self:termX() + self.cursorPos - self.displayOffset, self:termY() + (self.h / 2))\\\\\\\
5523\\\\009\\\\009end\\\\\\\
5524\\\\009end;\\\\\\\
5525\\\\009click = function (self, x, y)\\\\\\\
5526\\\\009\\\\009if ((x >= self:termX()) and (x <= (self:termX() + self.w - 1)) and (y >= self:termY()) and (y <= (self:termY() + self.h - 1))) then\\\\\\\
5527\\\\009\\\\009\\\\009self.active = true\\\\\\\
5528\\\\009\\\\009else\\\\\\\
5529\\\\009\\\\009\\\\009self.active = false\\\\\\\
5530\\\\009\\\\009end\\\\\\\
5531\\\\009end;\\\\\\\
5532\\\\009action = function(self)\\\\\\\
5533\\\\009end;\\\\\\\
5534\\\\009key = function(self, keyCode)\\\\\\\
5535\\\\009\\\\009if (self.active == false) then\\\\\\\
5536\\\\009\\\\009\\\\009return\\\\\\\
5537\\\\009\\\\009end\\\\\\\
5538\\\\009\\\\009if (keyCode == keys.backspace) then\\\\\\\
5539\\\\009\\\\009\\\\009if (self.cursorPos > 0) then\\\\\\\
5540\\\\009\\\\009\\\\009\\\\009self.text = string.sub(self.text, 1, self.cursorPos - 1) .. string.sub(self.text, self.cursorPos + 1)\\\\\\\
5541\\\\009\\\\009\\\\009\\\\009self.cursorPos = self.cursorPos - 1\\\\\\\
5542\\\\009\\\\009\\\\009\\\\009if (self.cursorPos - self.displayOffset < 0) then\\\\\\\
5543\\\\009\\\\009\\\\009\\\\009\\\\009self.displayOffset = self.displayOffset - 1\\\\\\\
5544\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5545\\\\009\\\\009\\\\009\\\\009self:draw()\\\\\\\
5546\\\\009\\\\009\\\\009end\\\\\\\
5547\\\\009\\\\009elseif (keyCode == keys.left) then\\\\\\\
5548\\\\009\\\\009\\\\009if (self.cursorPos > 0) then\\\\\\\
5549\\\\009\\\\009\\\\009\\\\009self.cursorPos = self.cursorPos - 1\\\\\\\
5550\\\\009\\\\009\\\\009\\\\009if (self.cursorPos - self.displayOffset < 0) then\\\\\\\
5551\\\\009\\\\009\\\\009\\\\009\\\\009self.displayOffset = self.displayOffset - 1\\\\\\\
5552\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5553\\\\009\\\\009\\\\009\\\\009self:draw()\\\\\\\
5554\\\\009\\\\009\\\\009end\\\\\\\
5555\\\\009\\\\009elseif (keyCode == keys.right) then\\\\\\\
5556\\\\009\\\\009\\\\009if (self.cursorPos < string.len(self.text)) then\\\\\\\
5557\\\\009\\\\009\\\\009\\\\009self.cursorPos = self.cursorPos + 1\\\\\\\
5558\\\\009\\\\009\\\\009\\\\009if (self.cursorPos - self.displayOffset > self.w - 1) then\\\\\\\
5559\\\\009\\\\009\\\\009\\\\009\\\\009self.displayOffset = self.displayOffset + 1\\\\\\\
5560\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5561\\\\009\\\\009\\\\009\\\\009self:draw()\\\\\\\
5562\\\\009\\\\009\\\\009end\\\\\\\
5563\\\\009\\\\009elseif (keyCode == keys.enter) then\\\\\\\
5564\\\\009\\\\009\\\\009self:action()\\\\\\\
5565\\\\009\\\\009end\\\\\\\
5566\\\\009end;\\\\\\\
5567\\\\009char = function(self, char)\\\\\\\
5568\\\\009\\\\009if (self.active == false) then\\\\\\\
5569\\\\009\\\\009\\\\009return\\\\\\\
5570\\\\009\\\\009end\\\\\\\
5571\\\\009\\\\009self.text = string.sub(self.text, 1, self.cursorPos) .. char .. string.sub(self.text, self.cursorPos + 1)\\\\\\\
5572\\\\009\\\\009if (self.cursorPos - self.displayOffset > self.w - 2) then\\\\\\\
5573\\\\009\\\\009\\\\009self.displayOffset = self.displayOffset + 1\\\\\\\
5574\\\\009\\\\009end\\\\\\\
5575\\\\009\\\\009self.cursorPos = self.cursorPos + 1\\\\\\\
5576\\\\009end;\\\\\\\
5577\\\\009update = function(self)\\\\\\\
5578\\\\009\\\\009if (self.active) then\\\\\\\
5579\\\\009\\\\009\\\\009self:draw()\\\\\\\
5580\\\\009\\\\009end\\\\\\\
5581\\\\009end;\\\\\\\
5582}\\\\\\\
5583TextField.mt = {\\\\\\\
5584\\\\009__index = function (table, key)\\\\\\\
5585\\\\009\\\\009if (TextField.prototype[key] ~= nil) then\\\\\\\
5586\\\\009\\\\009\\\\009return TextField.prototype[key]\\\\\\\
5587\\\\009\\\\009else\\\\\\\
5588\\\\009\\\\009\\\\009return Component.prototype[key]\\\\\\\
5589\\\\009\\\\009end\\\\\\\
5590\\\\009end;\\\\\\\
5591}\\\\\\\
5592function TextField:new(textFieldTbl)\\\\\\\
5593\\\\009if (textFieldTbl == nil) then\\\\\\\
5594\\\\009\\\\009textFieldTbl = self\\\\\\\
5595\\\\009end\\\\\\\
5596\\\\009setmetatable(textFieldTbl, TextField.mt)\\\\\\\
5597\\\\009return textFieldTbl\\\\\\\
5598end\\\\\\\
5599\\\\\\\
5600-- --\\\\\\\
5601-- List extends Component\\\\\\\
5602-- A component that lets you hold lists of other components\\\\\\\
5603-- --\\\\\\\
5604List = {}\\\\\\\
5605List.prototype = {\\\\\\\
5606\\\\009--vars\\\\\\\
5607\\\\009h = 5;\\\\\\\
5608\\\\009w = 16;\\\\\\\
5609\\\\009bgColor = colors.white;\\\\\\\
5610\\\\009bgColorStripe = colors.lightGray;\\\\\\\
5611\\\\009textColor = colors.black;\\\\\\\
5612\\\\009textColorStripe = colors.black;\\\\\\\
5613\\\\009activeColor = colors.gray;\\\\\\\
5614\\\\009activeTextColor = colors.white;\\\\\\\
5615\\\\009textAlign = \\\\\\\"left\\\\\\\";\\\\\\\
5616\\\\009scrollBarColor = colors.gray;\\\\\\\
5617\\\\009scrollBarTextColor = colors.white;\\\\\\\
5618\\\\009scrollBar = true;\\\\\\\
5619\\\\009wrapText = false;\\\\\\\
5620\\\\009displayOffset = 0;\\\\\\\
5621\\\\009components = {};\\\\\\\
5622\\\\009active = false;\\\\\\\
5623\\\\009--functions\\\\\\\
5624\\\\009draw = function(self)\\\\\\\
5625\\\\009\\\\009Utils:drawRect(self:termX(), self:termY(), self.w, self.h, self.bgColor)\\\\\\\
5626\\\\009\\\\009term.setBackgroundColor(self.bgColor)\\\\\\\
5627\\\\009\\\\009-- draw the components\\\\\\\
5628\\\\009\\\\009local index = 1\\\\\\\
5629\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5630\\\\009\\\\009\\\\009val.w = self.w - (self.scrollBar and 1 or 0)\\\\\\\
5631\\\\009\\\\009\\\\009val.y = self.displayOffset + index\\\\\\\
5632\\\\009\\\\009\\\\009index = index + val.h\\\\\\\
5633\\\\009\\\\009\\\\009if ((val.y > 0) and (val.y <= self.h)) then\\\\\\\
5634\\\\009\\\\009\\\\009\\\\009val:draw()\\\\\\\
5635\\\\009\\\\009\\\\009end\\\\\\\
5636\\\\009\\\\009\\\\009self.components[key] = val\\\\\\\
5637\\\\009\\\\009end\\\\\\\
5638\\\\009\\\\009-- draw the scroll bar\\\\\\\
5639\\\\009\\\\009if (self.scrollBar) then\\\\\\\
5640\\\\009\\\\009\\\\009Utils:drawRect(self:termX() + self.w - 1, self:termY(), 1, self.h, self.scrollBarColor)\\\\\\\
5641\\\\009\\\\009\\\\009term.setBackgroundColor(self.scrollBarColor)\\\\\\\
5642\\\\009\\\\009\\\\009term.setTextColor(self.scrollBarTextColor)\\\\\\\
5643\\\\009\\\\009\\\\009term.setCursorPos(self:termX() + self.w - 1, self:termY())\\\\\\\
5644\\\\009\\\\009\\\\009term.write(\\\\\\\"^\\\\\\\")\\\\\\\
5645\\\\009\\\\009\\\\009term.setCursorPos(self:termX() + self.w - 1, self:termY() + self.h - 1)\\\\\\\
5646\\\\009\\\\009\\\\009term.write(\\\\\\\"v\\\\\\\")\\\\\\\
5647\\\\009\\\\009end\\\\\\\
5648\\\\009end;\\\\\\\
5649\\\\009click = function (self, x, y)\\\\\\\
5650\\\\009\\\\009for key, val in pairs(self.components) do\\\\\\\
5651\\\\009\\\\009\\\\009if ((val.y > 0) and (val.y <= self.h)) then\\\\\\\
5652\\\\009\\\\009\\\\009\\\\009val:click(x, y)\\\\\\\
5653\\\\009\\\\009\\\\009end\\\\\\\
5654\\\\009\\\\009end\\\\\\\
5655\\\\009\\\\009if ((x >= self:termX()) and (x <= (self:termX() + self.w - 1)) and (y >= self:termY()) and (y <= (self:termY() + self.h - 1))) then\\\\\\\
5656\\\\009\\\\009\\\\009self.active = true\\\\\\\
5657\\\\009\\\\009else\\\\\\\
5658\\\\009\\\\009\\\\009self.active = false\\\\\\\
5659\\\\009\\\\009end\\\\\\\
5660\\\\009\\\\009if (self.scrollBar) then\\\\\\\
5661\\\\009\\\\009\\\\009if ((x == self:termX() + self.w - 1) and (y == self:termY())) then\\\\\\\
5662\\\\009\\\\009\\\\009\\\\009if (self.displayOffset < 0) then\\\\\\\
5663\\\\009\\\\009\\\\009\\\\009\\\\009self.displayOffset = self.displayOffset + 1\\\\\\\
5664\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5665\\\\009\\\\009\\\\009end\\\\\\\
5666\\\\009\\\\009\\\\009if ((x == self:termX() + self.w - 1) and (y == self:termY() + self.h - 1)) then\\\\\\\
5667\\\\009\\\\009\\\\009\\\\009if (self.displayOffset > -#self.components + 1) then\\\\\\\
5668\\\\009\\\\009\\\\009\\\\009\\\\009self.displayOffset = self.displayOffset - 1\\\\\\\
5669\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5670\\\\009\\\\009\\\\009end\\\\\\\
5671\\\\009\\\\009end\\\\\\\
5672\\\\009end;\\\\\\\
5673\\\\009scroll = function (self, direction)\\\\\\\
5674\\\\009\\\\009if (self.active) then\\\\\\\
5675\\\\009\\\\009\\\\009if (direction == -1) then\\\\\\\
5676\\\\009\\\\009\\\\009\\\\009if (self.displayOffset < 0) then\\\\\\\
5677\\\\009\\\\009\\\\009\\\\009\\\\009self.displayOffset = self.displayOffset + 1\\\\\\\
5678\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5679\\\\009\\\\009\\\\009end\\\\\\\
5680\\\\009\\\\009\\\\009if (direction == 1) then\\\\\\\
5681\\\\009\\\\009\\\\009\\\\009if (self.displayOffset > -#self.components + 1) then\\\\\\\
5682\\\\009\\\\009\\\\009\\\\009\\\\009self.displayOffset = self.displayOffset - 1\\\\\\\
5683\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5684\\\\009\\\\009\\\\009end\\\\\\\
5685\\\\009\\\\009end\\\\\\\
5686\\\\009end;\\\\\\\
5687\\\\009addComponent = function(self, componentTbl)\\\\\\\
5688\\\\009\\\\009componentTbl.h = 1\\\\\\\
5689\\\\009\\\\009componentTbl.w = self.w - (self.scrollBar and 1 or 0)\\\\\\\
5690\\\\009\\\\009if (not self.wrapText) then\\\\\\\
5691\\\\009\\\\009\\\\009componentTbl.text = Utils:limitText(componentTbl.text, componentTbl.w, \\\\\\\"...\\\\\\\")\\\\\\\
5692\\\\009\\\\009else\\\\\\\
5693\\\\009\\\\009\\\\009if (string.len(componentTbl.text) > componentTbl.w) then\\\\\\\
5694\\\\009\\\\009\\\\009\\\\009componentTbl.h = math.ceil(string.len(componentTbl.text) / componentTbl.w)\\\\\\\
5695\\\\009\\\\009\\\\009\\\\009componentTbl.text = Utils:wrapText(componentTbl.text, componentTbl.w)\\\\\\\
5696\\\\009\\\\009\\\\009end\\\\\\\
5697\\\\009\\\\009end\\\\\\\
5698\\\\009\\\\009componentTbl.bgColor = (#self.components % 2 == 0 and self.bgColor or self.bgColorStripe)\\\\\\\
5699\\\\009\\\\009componentTbl.textColor = (#self.components % 2 == 0 and self.textColor or self.textColorStripe)\\\\\\\
5700\\\\009\\\\009componentTbl.textAlign = self.textAlign\\\\\\\
5701\\\\009\\\\009componentTbl.activeColor = self.activeColor\\\\\\\
5702\\\\009\\\\009componentTbl.activeTextColor = self.activeTextColor\\\\\\\
5703\\\\009\\\\009componentTbl.parent = self\\\\\\\
5704\\\\009\\\\009componentTbl.removed = false\\\\\\\
5705\\\\009\\\\009table.insert(self.components, componentTbl)\\\\\\\
5706\\\\009end;\\\\\\\
5707\\\\009update = function(self) return false end;\\\\\\\
5708}\\\\\\\
5709List.mt = {\\\\\\\
5710\\\\009__index = function (table, key)\\\\\\\
5711\\\\009\\\\009if (List.prototype[key] ~= nil) then\\\\\\\
5712\\\\009\\\\009\\\\009return List.prototype[key]\\\\\\\
5713\\\\009\\\\009else\\\\\\\
5714\\\\009\\\\009\\\\009return Component.prototype[key]\\\\\\\
5715\\\\009\\\\009end\\\\\\\
5716\\\\009end;\\\\\\\
5717}\\\\\\\
5718function List:new(listTbl)\\\\\\\
5719\\\\009if (listTbl == nil) then\\\\\\\
5720\\\\009\\\\009listTbl = self\\\\\\\
5721\\\\009end\\\\\\\
5722\\\\009setmetatable(listTbl, List.mt)\\\\\\\
5723\\\\009listTbl.components = {}\\\\\\\
5724\\\\009return listTbl\\\\\\\
5725end\\\\\\\
5726\\\\\\\
5727-- --\\\\\\\
5728-- Checkbox extends Component\\\\\\\
5729-- A component that lets users make a boolean choice\\\\\\\
5730-- --\\\\\\\
5731Checkbox = {}\\\\\\\
5732Checkbox.prototype = {\\\\\\\
5733\\\\009--vars\\\\\\\
5734\\\\009h = 1;\\\\\\\
5735\\\\009w = 16;\\\\\\\
5736\\\\009bgColor = colors.lightGray;\\\\\\\
5737\\\\009boxColor = colors.white;\\\\\\\
5738\\\\009textColor = colors.black;\\\\\\\
5739\\\\009checkedChar = \\\\\\\"X\\\\\\\";\\\\\\\
5740\\\\009checked = false;\\\\\\\
5741\\\\009text = \\\\\\\"txUI Checkbox\\\\\\\";\\\\\\\
5742\\\\009textPosition = \\\\\\\"right\\\\\\\";\\\\\\\
5743\\\\009--functions\\\\\\\
5744\\\\009draw = function(self)\\\\\\\
5745\\\\009\\\\009Utils:drawRect(self:termX(), self:termY(), self.w, self.h, self.bgColor)\\\\\\\
5746\\\\009\\\\009-- draw box and set label position\\\\\\\
5747\\\\009\\\\009term.setBackgroundColor(self.boxColor)\\\\\\\
5748\\\\009\\\\009term.setTextColor(self.textColor)\\\\\\\
5749\\\\009\\\\009if (self.textPosition == \\\\\\\"right\\\\\\\") then\\\\\\\
5750\\\\009\\\\009\\\\009Utils:drawRect(self:termX(), self:termY(), 1, 1, self.boxColor)\\\\\\\
5751\\\\009\\\\009\\\\009term.setCursorPos(self:termX(), self:termY())\\\\\\\
5752\\\\009\\\\009\\\\009term.write(self.checked and self.checkedChar or \\\\\\\" \\\\\\\")\\\\\\\
5753\\\\009\\\\009\\\\009term.setCursorPos(self:termX() + 2, self:termY())\\\\\\\
5754\\\\009\\\\009elseif (self.textPosition == \\\\\\\"left\\\\\\\") then\\\\\\\
5755\\\\009\\\\009\\\\009Utils:drawRect(self:termX() + self.w - 1, self:termY(), 1, 1, self.boxColor)\\\\\\\
5756\\\\009\\\\009\\\\009term.setCursorPos(self:termX() + self.w - 1, self:termY())\\\\\\\
5757\\\\009\\\\009\\\\009term.write(self.checked and self.checkedChar or \\\\\\\" \\\\\\\")\\\\\\\
5758\\\\009\\\\009\\\\009term.setCursorPos(self:termX() + self.w - string.len(self.text) - 2, self:termY())\\\\\\\
5759\\\\009\\\\009end\\\\\\\
5760\\\\009\\\\009-- draw label\\\\\\\
5761\\\\009\\\\009term.setBackgroundColor(self.bgColor)\\\\\\\
5762\\\\009\\\\009term.write(self.text)\\\\\\\
5763\\\\009end;\\\\\\\
5764\\\\009click = function (self, x, y)\\\\\\\
5765\\\\009\\\\009if ((x >= self:termX()) and (x <= (self:termX() + self.w - 1)) and (y >= self:termY()) and (y <= (self:termY() + self.h - 1))) then\\\\\\\
5766\\\\009\\\\009\\\\009self.checked = not self.checked\\\\\\\
5767\\\\009\\\\009end\\\\\\\
5768\\\\009end;\\\\\\\
5769\\\\009update = function(self) return false end;\\\\\\\
5770}\\\\\\\
5771Checkbox.mt = {\\\\\\\
5772\\\\009__index = function (table, key)\\\\\\\
5773\\\\009\\\\009if (Checkbox.prototype[key] ~= nil) then\\\\\\\
5774\\\\009\\\\009\\\\009return Checkbox.prototype[key]\\\\\\\
5775\\\\009\\\\009else\\\\\\\
5776\\\\009\\\\009\\\\009return Component.prototype[key]\\\\\\\
5777\\\\009\\\\009end\\\\\\\
5778\\\\009end;\\\\\\\
5779}\\\\\\\
5780function Checkbox:new(checkboxTbl)\\\\\\\
5781\\\\009if (checkboxTbl == nil) then\\\\\\\
5782\\\\009\\\\009checkboxTbl = self\\\\\\\
5783\\\\009end\\\\\\\
5784\\\\009setmetatable(checkboxTbl, Checkbox.mt)\\\\\\\
5785\\\\009return checkboxTbl\\\\\\\
5786end\\\\\\\
5787\\\\\\\
5788-- --\\\\\\\
5789-- ProgressBar extends Component\\\\\\\
5790-- A component that shows progress\\\\\\\
5791-- --\\\\\\\
5792ProgressBar = {}\\\\\\\
5793ProgressBar.prototype = {\\\\\\\
5794\\\\009--vars\\\\\\\
5795\\\\009h = 1;\\\\\\\
5796\\\\009w = 16;\\\\\\\
5797\\\\009val = 0;\\\\\\\
5798\\\\009bgColor = colors.white;\\\\\\\
5799\\\\009barColor = colors.lime;\\\\\\\
5800\\\\009textColor = colors.black;\\\\\\\
5801\\\\009barTextColor = colors.white;\\\\\\\
5802\\\\009textAlign = \\\\\\\"center\\\\\\\";\\\\\\\
5803\\\\009textMask = \\\\\\\"{val}%\\\\\\\";\\\\\\\
5804\\\\009showText = true;\\\\\\\
5805\\\\009vertCenter = true;\\\\\\\
5806\\\\009--functions\\\\\\\
5807\\\\009draw = function(self)\\\\\\\
5808\\\\009\\\\009if (self.val > 100) then\\\\\\\
5809\\\\009\\\\009\\\\009self.val = 100\\\\\\\
5810\\\\009\\\\009end\\\\\\\
5811\\\\009\\\\009local barWidth = self.w * (self.val / 100)\\\\\\\
5812\\\\009\\\\009Utils:drawRect(self:termX(), self:termY(), self.w, self.h, self.bgColor)\\\\\\\
5813\\\\009\\\\009Utils:drawRect(self:termX(), self:termY(), barWidth, self.h, self.barColor)\\\\\\\
5814\\\\009\\\\009if (self.showText) then\\\\\\\
5815\\\\009\\\\009\\\\009local text = string.gsub(self.textMask, \\\\\\\"{val}\\\\\\\", tostring(self.val))\\\\\\\
5816\\\\009\\\\009\\\\009term.setBackgroundColor(self.bgColor)\\\\\\\
5817\\\\009\\\\009\\\\009term.setTextColor(self.textColor)\\\\\\\
5818\\\\009\\\\009\\\\009local lines = #Utils:splitText(text, \\\\\\\"\\\\\\\\n\\\\\\\")\\\\\\\
5819\\\\009\\\\009\\\\009for k, v in ipairs(Utils:splitText(text, \\\\\\\"\\\\\\\\n\\\\\\\")) do\\\\\\\
5820\\\\009\\\\009\\\\009\\\\009term.setCursorPos(Utils:alignText(self.textAlign, string.len(v), self:termX(), self.w), self:termY() + k - 1 + (self.vertCenter and ((self.h - lines) / 2) or 0))\\\\\\\
5821\\\\009\\\\009\\\\009\\\\009local x, y = term.getCursorPos()\\\\\\\
5822\\\\009\\\\009\\\\009\\\\009if (x - self:termX() < barWidth) then\\\\\\\
5823\\\\009\\\\009\\\\009\\\\009\\\\009term.setBackgroundColor(self.barColor)\\\\\\\
5824\\\\009\\\\009\\\\009\\\\009\\\\009term.setTextColor(self.barTextColor)\\\\\\\
5825\\\\009\\\\009\\\\009\\\\009\\\\009term.write(v)\\\\\\\
5826\\\\009\\\\009\\\\009\\\\009\\\\009if (x - self:termX() + string.len(v) > barWidth) then\\\\\\\
5827\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009term.setBackgroundColor(self.bgColor)\\\\\\\
5828\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009term.setTextColor(self.textColor)\\\\\\\
5829\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009local overflow = x - self:termX() + string.len(v) - barWidth\\\\\\\
5830\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009local ax, ay = term.getCursorPos()\\\\\\\
5831\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009term.setCursorPos(ax - overflow, ay)\\\\\\\
5832\\\\009\\\\009\\\\009\\\\009\\\\009\\\\009term.write(string.sub(v, math.abs(string.len(v) - overflow) + 1))\\\\\\\
5833\\\\009\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5834\\\\009\\\\009\\\\009\\\\009else\\\\\\\
5835\\\\009\\\\009\\\\009\\\\009\\\\009term.write(v)\\\\\\\
5836\\\\009\\\\009\\\\009\\\\009end\\\\\\\
5837\\\\009\\\\009\\\\009end\\\\\\\
5838\\\\009\\\\009end\\\\\\\
5839\\\\009end;\\\\\\\
5840\\\\009update = function(self) return false end;\\\\\\\
5841}\\\\\\\
5842ProgressBar.mt = {\\\\\\\
5843\\\\009__index = function (table, key)\\\\\\\
5844\\\\009\\\\009if (ProgressBar.prototype[key] ~= nil) then\\\\\\\
5845\\\\009\\\\009\\\\009return ProgressBar.prototype[key]\\\\\\\
5846\\\\009\\\\009else\\\\\\\
5847\\\\009\\\\009\\\\009return Component.prototype[key]\\\\\\\
5848\\\\009\\\\009end\\\\\\\
5849\\\\009end;\\\\\\\
5850}\\\\\\\
5851function ProgressBar:new(progressBarTbl)\\\\\\\
5852\\\\009if (progressBarTbl == nil) then\\\\\\\
5853\\\\009\\\\009progressBarTbl = self\\\\\\\
5854\\\\009end\\\\\\\
5855\\\\009setmetatable(progressBarTbl, ProgressBar.mt)\\\\\\\
5856\\\\009return progressBarTbl\\\\\\\
5857end\\\\\\\
5858\\\\\\\
5859Controller:setDefaultStyle(Style:new({}))\\\\\\\
5860]]\\\\\\\
5861\\\\\\\
5862persist(\\\\\\\"GUI\\\\\\\", libcode)\\\\\\\
5863\\\\\\\
5864return 1\\\"\",\
5865 \"F:libstdlua.2.so\",\
5866 \"\\\"local libcode = [[\\\\\\\
5867--\\\\\\\
5868--Copyright (C) 2012 Thomas Farr a.k.a tomass1996 [farr.thomas@gmail.com]\\\\\\\
5869--Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\\\\\\\
5870--associated documentation files (the \\\\\\\"Software\\\\\\\"), to deal in the Software without restriction,\\\\\\\
5871--including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,\\\\\\\
5872--copies of the Software, and to permit persons to whom the Software is furnished to do so,\\\\\\\
5873--subject to the following conditions:\\\\\\\
5874---The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\\\\\\\
5875---Visible credit is given to the original author.\\\\\\\
5876---The software is distributed in a non-profit way.\\\\\\\
5877--THE SOFTWARE IS PROVIDED \\\\\\\"AS IS\\\\\\\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\\\\\\\
5878--WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\\\\\\\
5879--COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\\\\\\\
5880--ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\\\\\\\
5881--\\\\\\\
5882\\\\\\\
5883local floor,modf, insert = math.floor,math.modf, table.insert\\\\\\\
5884local char,format,rep = string.char,string.format,string.rep\\\\\\\
5885\\\\\\\
5886local function basen(n,b)\\\\\\\
5887\\\\009if n < 0 then\\\\\\\
5888\\\\009\\\\009n = -n\\\\\\\
5889\\\\009end\\\\\\\
5890 local t = \\\\\\\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\\\\]^_abcdefghijklmnopqrstuvwxyz{|}~\\\\\\\"\\\\\\\
5891 if n < b then\\\\\\\
5892\\\\009local ret = \\\\\\\"\\\\\\\"\\\\\\\
5893\\\\009ret = ret..string.sub(t, (n%b)+1,(n%b)+1)\\\\\\\
5894\\\\009return ret\\\\\\\
5895 else\\\\\\\
5896\\\\009local tob = tostring(basen(math.floor(n/b), b))\\\\\\\
5897\\\\009local ret = tob..t:sub((n%b)+1,(n%b)+1)\\\\\\\
5898\\\\009return ret\\\\\\\
5899 end\\\\\\\
5900end\\\\\\\
5901\\\\\\\
5902local Base64 = {}\\\\\\\
5903Base64[\\\\\\\"lsh\\\\\\\"] = function(value,shift)\\\\\\\
5904 return (value*(2^shift)) % 256\\\\\\\
5905end\\\\\\\
5906Base64[\\\\\\\"rsh\\\\\\\"] = function(value,shift)\\\\\\\
5907 return math.floor(value/2^shift) % 256\\\\\\\
5908end\\\\\\\
5909Base64[\\\\\\\"bit\\\\\\\"] = function(x,b)\\\\\\\
5910 return (x % 2^b - x % 2^(b-1) > 0)\\\\\\\
5911end\\\\\\\
5912Base64[\\\\\\\"lor\\\\\\\"] = function(x,y)\\\\\\\
5913 local result = 0\\\\\\\
5914 for p=1,8 do result = result + (((Base64.bit(x,p) or Base64.bit(y,p)) == true) and 2^(p-1) or 0) end\\\\\\\
5915 return result\\\\\\\
5916end\\\\\\\
5917Base64[\\\\\\\"base64chars\\\\\\\"] = {\\\\\\\
5918 [0]='A',[1]='B',[2]='C',[3]='D',[4]='E',[5]='F',[6]='G',[7]='H',[8]='I',[9]='J',[10]='K',\\\\\\\
5919 [11]='L',[12]='M',[13]='N',[14]='O',[15]='P',[16]='Q',[17]='R',[18]='S',[19]='T',[20]='U',\\\\\\\
5920 [21]='V',[22]='W',[23]='X',[24]='Y',[25]='Z',[26]='a',[27]='b',[28]='c',[29]='d',[30]='e',\\\\\\\
5921 [31]='f',[32]='g',[33]='h',[34]='i',[35]='j',[36]='k',[37]='l',[38]='m',[39]='n',[40]='o',\\\\\\\
5922 [41]='p',[42]='q',[43]='r',[44]='s',[45]='t',[46]='u',[47]='v',[48]='w',[49]='x',[50]='y',\\\\\\\
5923 [51]='z',[52]='0',[53]='1',[54]='2',[55]='3',[56]='4',[57]='5',[58]='6',[59]='7',[60]='8',\\\\\\\
5924 [61]='9',[62]='-',[63]='_'}\\\\\\\
5925Base64[\\\\\\\"base64bytes\\\\\\\"] = {\\\\\\\
5926 ['A']=0,['B']=1,['C']=2,['D']=3,['E']=4,['F']=5,['G']=6,['H']=7,['I']=8,['J']=9,['K']=10,\\\\\\\
5927 ['L']=11,['M']=12,['N']=13,['O']=14,['P']=15,['Q']=16,['R']=17,['S']=18,['T']=19,['U']=20,\\\\\\\
5928 ['V']=21,['W']=22,['X']=23,['Y']=24,['Z']=25,['a']=26,['b']=27,['c']=28,['d']=29,['e']=30,\\\\\\\
5929 ['f']=31,['g']=32,['h']=33,['i']=34,['j']=35,['k']=36,['l']=37,['m']=38,['n']=39,['o']=40,\\\\\\\
5930 ['p']=41,['q']=42,['r']=43,['s']=44,['t']=45,['u']=46,['v']=47,['w']=48,['x']=49,['y']=50,\\\\\\\
5931 ['z']=51,['0']=52,['1']=53,['2']=54,['3']=55,['4']=56,['5']=57,['6']=58,['7']=59,['8']=60,\\\\\\\
5932 ['9']=61,['-']=62,['_']=63,['=']=nil}\\\\\\\
5933\\\\\\\
5934local base32 = \\\\\\\"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567\\\\\\\"\\\\\\\
5935\\\\\\\
5936local tSHA1 = {}\\\\\\\
5937tSHA1[\\\\\\\"bytes_to_w32\\\\\\\"] = function(a,b,c,d) return a*0x1000000+b*0x10000+c*0x100+d end\\\\\\\
5938tSHA1[\\\\\\\"w32_to_bytes\\\\\\\"] = function(i) return floor(i/0x1000000)%0x100,floor(i/0x10000)%0x100,floor(i/0x100)%0x100,i%0x100 end\\\\\\\
5939tSHA1[\\\\\\\"w32_rot\\\\\\\"] = function(bits,a)\\\\\\\
5940 local b2 = 2^(32-bits)\\\\\\\
5941 local a,b = modf(a/b2)\\\\\\\
5942 return a+b*b2*(2^(bits))\\\\\\\
5943end\\\\\\\
5944tSHA1[\\\\\\\"byte_to_bits\\\\\\\"] = function(b)\\\\\\\
5945 local b = function (n)\\\\\\\
5946 local b = floor(b/n)\\\\\\\
5947 return b%2==1\\\\\\\
5948 end\\\\\\\
5949 return b(1),b(2),b(4),b(8),b(16),b(32),b(64),b(128)\\\\\\\
5950end\\\\\\\
5951tSHA1[\\\\\\\"bits_to_byte\\\\\\\"] = function(a,b,c,d,e,f,g,h)\\\\\\\
5952 local function n(b,x) return b and x or 0 end\\\\\\\
5953 return n(a,1)+n(b,2)+n(c,4)+n(d,8)+n(e,16)+n(f,32)+n(g,64)+n(h,128)\\\\\\\
5954end\\\\\\\
5955tSHA1[\\\\\\\"bits_to_string\\\\\\\"] = function(a,b,c,d,e,f,g,h)\\\\\\\
5956 local function x(b) return b and \\\\\\\"1\\\\\\\" or \\\\\\\"0\\\\\\\" end\\\\\\\
5957 return (\\\\\\\"%s%s%s%s %s%s%s%s\\\\\\\"):format(x(a),x(b),x(c),x(d),x(e),x(f),x(g),x(h))\\\\\\\
5958end\\\\\\\
5959tSHA1[\\\\\\\"byte_to_bit_string\\\\\\\"] = function(b) return tSHA1.bits_to_string(byte_to_bits(b)) end\\\\\\\
5960tSHA1[\\\\\\\"w32_to_bit_string\\\\\\\"] = function(a)\\\\\\\
5961 if type(a) == \\\\\\\"string\\\\\\\" then return a end\\\\\\\
5962 local aa,ab,ac,ad = tSHA1.w32_to_bytes(a)\\\\\\\
5963 local s = tSHA1.byte_to_bit_string\\\\\\\
5964 return (\\\\\\\"%s %s %s %s\\\\\\\"):format(s(aa):reverse(),s(ab):reverse(),s(ac):reverse(),s(ad):reverse()):reverse()\\\\\\\
5965end\\\\\\\
5966tSHA1[\\\\\\\"band\\\\\\\"] = function(a,b)\\\\\\\
5967 local A,B,C,D,E,F,G,H = tSHA1.byte_to_bits(b)\\\\\\\
5968 local a,b,c,d,e,f,g,h = tSHA1.byte_to_bits(a)\\\\\\\
5969 return tSHA1.bits_to_byte(\\\\\\\
5970 A and a, B and b, C and c, D and d,\\\\\\\
5971 E and e, F and f, G and g, H and h)\\\\\\\
5972end\\\\\\\
5973tSHA1[\\\\\\\"bor\\\\\\\"] = function(a,b)\\\\\\\
5974 local A,B,C,D,E,F,G,H = tSHA1.byte_to_bits(b)\\\\\\\
5975 local a,b,c,d,e,f,g,h = tSHA1.byte_to_bits(a)\\\\\\\
5976 return tSHA1.bits_to_byte(\\\\\\\
5977 A or a, B or b, C or c, D or d,\\\\\\\
5978 E or e, F or f, G or g, H or h)\\\\\\\
5979end\\\\\\\
5980tSHA1[\\\\\\\"bxor\\\\\\\"] = function(a,b)\\\\\\\
5981 local A,B,C,D,E,F,G,H = tSHA1.byte_to_bits(b)\\\\\\\
5982 local a,b,c,d,e,f,g,h = tSHA1.byte_to_bits(a)\\\\\\\
5983 return tSHA1.bits_to_byte(\\\\\\\
5984 A ~= a, B ~= b, C ~= c, D ~= d,\\\\\\\
5985 E ~= e, F ~= f, G ~= g, H ~= h)\\\\\\\
5986end\\\\\\\
5987tSHA1[\\\\\\\"bnot\\\\\\\"] = function(x) return 255-(x % 256) end\\\\\\\
5988tSHA1[\\\\\\\"w32_comb\\\\\\\"] = function(fn)\\\\\\\
5989 return function (a,b)\\\\\\\
5990 local aa,ab,ac,ad = tSHA1.w32_to_bytes(a)\\\\\\\
5991 local ba,bb,bc,bd = tSHA1.w32_to_bytes(b)\\\\\\\
5992 return tSHA1.bytes_to_w32(fn(aa,ba),fn(ab,bb),fn(ac,bc),fn(ad,bd))\\\\\\\
5993 end\\\\\\\
5994end\\\\\\\
5995tSHA1[\\\\\\\"w32_xor_n\\\\\\\"] = function(a,...)\\\\\\\
5996 local aa,ab,ac,ad = tSHA1.w32_to_bytes(a)\\\\\\\
5997 for i=1,select('#',...) do\\\\\\\
5998 local ba,bb,bc,bd = tSHA1.w32_to_bytes(select(i,...))\\\\\\\
5999 aa,ab,ac,ad = tSHA1.bxor(aa,ba),tSHA1.bxor(ab,bb),tSHA1.bxor(ac,bc),tSHA1.bxor(ad,bd)\\\\\\\
6000 end\\\\\\\
6001 return tSHA1.bytes_to_w32(aa,ab,ac,ad)\\\\\\\
6002end\\\\\\\
6003tSHA1[\\\\\\\"w32_or3\\\\\\\"] = function(a,b,c)\\\\\\\
6004 local aa,ab,ac,ad = tSHA1.w32_to_bytes(a)\\\\\\\
6005 local ba,bb,bc,bd = tSHA1.w32_to_bytes(b)\\\\\\\
6006 local ca,cb,cc,cd = tSHA1.w32_to_bytes(c)\\\\\\\
6007 return tSHA1.bytes_to_w32(\\\\\\\
6008 tSHA1.bor(aa,tSHA1.bor(ba,ca)), tSHA1.bor(ab,tSHA1.bor(bb,cb)), tSHA1.bor(ac,tSHA1.bor(bc,cc)), tSHA1.bor(ad,tSHA1.bor(bd,cd))\\\\\\\
6009 )\\\\\\\
6010end\\\\\\\
6011tSHA1[\\\\\\\"w32_not\\\\\\\"] = function(a) return 4294967295-(a % 4294967296) end\\\\\\\
6012tSHA1[\\\\\\\"w32_add\\\\\\\"] = function(a,b) return (a+b) % 4294967296 end\\\\\\\
6013tSHA1[\\\\\\\"w32_add_n\\\\\\\"] = function(a,...)\\\\\\\
6014 for i=1,select('#',...) do\\\\\\\
6015 a = (a+select(i,...)) % 4294967296\\\\\\\
6016 end\\\\\\\
6017 return a\\\\\\\
6018end\\\\\\\
6019tSHA1[\\\\\\\"w32_to_hexstring\\\\\\\"] = function(w) return format(\\\\\\\"%08x\\\\\\\",w) end\\\\\\\
6020tSHA1[\\\\\\\"w32_and\\\\\\\"] = tSHA1.w32_comb(tSHA1.band)\\\\\\\
6021tSHA1[\\\\\\\"w32_xor\\\\\\\"] = tSHA1.w32_comb(tSHA1.bxor)\\\\\\\
6022tSHA1[\\\\\\\"w32_or\\\\\\\"] = tSHA1.w32_comb(tSHA1.bor)\\\\\\\
6023\\\\\\\
6024local CRC = {}\\\\\\\
6025CRC.crc32 = {\\\\\\\
6026 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,\\\\\\\
6027 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,\\\\\\\
6028 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,\\\\\\\
6029 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,\\\\\\\
6030 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,\\\\\\\
6031 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,\\\\\\\
6032 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,\\\\\\\
6033 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,\\\\\\\
6034 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,\\\\\\\
6035 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,\\\\\\\
6036 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,\\\\\\\
6037 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,\\\\\\\
6038 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,\\\\\\\
6039 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,\\\\\\\
6040 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,\\\\\\\
6041 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,\\\\\\\
6042 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,\\\\\\\
6043 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,\\\\\\\
6044 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,\\\\\\\
6045 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,\\\\\\\
6046 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,\\\\\\\
6047 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,\\\\\\\
6048 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,\\\\\\\
6049 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,\\\\\\\
6050 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,\\\\\\\
6051 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,\\\\\\\
6052 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,\\\\\\\
6053 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,\\\\\\\
6054 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,\\\\\\\
6055 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,\\\\\\\
6056 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,\\\\\\\
6057 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,\\\\\\\
6058 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,\\\\\\\
6059 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,\\\\\\\
6060 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,\\\\\\\
6061 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,\\\\\\\
6062 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,\\\\\\\
6063 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,\\\\\\\
6064 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,\\\\\\\
6065 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,\\\\\\\
6066 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,\\\\\\\
6067 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,\\\\\\\
6068 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }\\\\\\\
6069\\\\\\\
6070local bit = {}\\\\\\\
6071bit[\\\\\\\"bnot\\\\\\\"] = function(n)\\\\\\\
6072 local tbl = bit.tobits(n)\\\\\\\
6073 local size = math.max(table.getn(tbl), 32)\\\\\\\
6074 for i = 1, size do\\\\\\\
6075 if(tbl[i] == 1) then\\\\\\\
6076 tbl[i] = 0\\\\\\\
6077 else\\\\\\\
6078 tbl[i] = 1\\\\\\\
6079 end\\\\\\\
6080 end\\\\\\\
6081 return bit.tonumb(tbl)\\\\\\\
6082end\\\\\\\
6083bit[\\\\\\\"band\\\\\\\"] = function(m, n)\\\\\\\
6084 local tbl_m = bit.tobits(m)\\\\\\\
6085 local tbl_n = bit.tobits(n)\\\\\\\
6086 bit.expand(tbl_m, tbl_n)\\\\\\\
6087 local tbl = {}\\\\\\\
6088 local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))\\\\\\\
6089 for i = 1, rslt do\\\\\\\
6090 if(tbl_m[i]== 0 or tbl_n[i] == 0) then\\\\\\\
6091 tbl[i] = 0\\\\\\\
6092 else\\\\\\\
6093 tbl[i] = 1\\\\\\\
6094 end\\\\\\\
6095 end\\\\\\\
6096 return bit.tonumb(tbl)\\\\\\\
6097end\\\\\\\
6098bit[\\\\\\\"bor\\\\\\\"] = function(m, n)\\\\\\\
6099 local tbl_m = bit.tobits(m)\\\\\\\
6100 local tbl_n = bit.tobits(n)\\\\\\\
6101 bit.expand(tbl_m, tbl_n)\\\\\\\
6102 local tbl = {}\\\\\\\
6103 local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))\\\\\\\
6104 for i = 1, rslt do\\\\\\\
6105 if(tbl_m[i]== 0 and tbl_n[i] == 0) then\\\\\\\
6106 tbl[i] = 0\\\\\\\
6107 else\\\\\\\
6108 tbl[i] = 1\\\\\\\
6109 end\\\\\\\
6110 end\\\\\\\
6111 return bit.tonumb(tbl)\\\\\\\
6112end\\\\\\\
6113bit[\\\\\\\"bxor\\\\\\\"] = function(m, n)\\\\\\\
6114 local tbl_m = bit.tobits(m)\\\\\\\
6115 local tbl_n = bit.tobits(n)\\\\\\\
6116 bit.expand(tbl_m, tbl_n)\\\\\\\
6117 local tbl = {}\\\\\\\
6118 local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))\\\\\\\
6119 for i = 1, rslt do\\\\\\\
6120 if(tbl_m[i] ~= tbl_n[i]) then\\\\\\\
6121 tbl[i] = 1\\\\\\\
6122 else\\\\\\\
6123 tbl[i] = 0\\\\\\\
6124 end\\\\\\\
6125 end\\\\\\\
6126 return bit.tonumb(tbl)\\\\\\\
6127end\\\\\\\
6128bit[\\\\\\\"brshift\\\\\\\"] = function(n, bits)\\\\\\\
6129 bit.checkint(n)\\\\\\\
6130 local high_bit = 0\\\\\\\
6131 if(n < 0) then\\\\\\\
6132 n = bit.bnot(math.abs(n)) + 1\\\\\\\
6133 high_bit = 2147483648\\\\\\\
6134 end\\\\\\\
6135 for i=1, bits do\\\\\\\
6136 n = n/2\\\\\\\
6137 n = bit.bor(math.floor(n), high_bit)\\\\\\\
6138 end\\\\\\\
6139 return math.floor(n)\\\\\\\
6140end\\\\\\\
6141bit[\\\\\\\"blshift\\\\\\\"] = function(n, bits)\\\\\\\
6142 bit.checkint(n)\\\\\\\
6143 if(n < 0) then\\\\\\\
6144 n = bit.bnot(math.abs(n)) + 1\\\\\\\
6145 end\\\\\\\
6146 for i=1, bits do\\\\\\\
6147 n = n*2\\\\\\\
6148 end\\\\\\\
6149 return bit.band(n, 4294967295)\\\\\\\
6150end\\\\\\\
6151bit[\\\\\\\"bxor2\\\\\\\"] = function(m, n)\\\\\\\
6152 local rhs = bit.bor(bit.bnot(m), bit.bnot(n))\\\\\\\
6153 local lhs = bit.bor(m, n)\\\\\\\
6154 local rslt = bit.band(lhs, rhs)\\\\\\\
6155 return rslt\\\\\\\
6156end\\\\\\\
6157bit[\\\\\\\"blogic_rshift\\\\\\\"] = function(n, bits)\\\\\\\
6158 bit.checkint(n)\\\\\\\
6159 if(n < 0) then\\\\\\\
6160 n = bit.bnot(math.abs(n)) + 1\\\\\\\
6161 end\\\\\\\
6162 for i=1, bits do\\\\\\\
6163 n = n/2\\\\\\\
6164 end\\\\\\\
6165 return math.floor(n)\\\\\\\
6166end\\\\\\\
6167bit[\\\\\\\"tobits\\\\\\\"] = function(n)\\\\\\\
6168 bit.checkint(n)\\\\\\\
6169 if(n < 0) then\\\\\\\
6170 return bit.tobits(bit.bnot(math.abs(n)) + 1)\\\\\\\
6171 end\\\\\\\
6172 local tbl = {}\\\\\\\
6173 local cnt = 1\\\\\\\
6174 while (n > 0) do\\\\\\\
6175 local last = math.fmod(n,2)\\\\\\\
6176 if(last == 1) then\\\\\\\
6177 tbl[cnt] = 1\\\\\\\
6178 else\\\\\\\
6179 tbl[cnt] = 0\\\\\\\
6180 end\\\\\\\
6181 n = (n-last)/2\\\\\\\
6182 cnt = cnt + 1\\\\\\\
6183 end\\\\\\\
6184 return tbl\\\\\\\
6185end\\\\\\\
6186bit[\\\\\\\"tonumb\\\\\\\"] = function(tbl)\\\\\\\
6187 local n = table.getn(tbl)\\\\\\\
6188 local rslt = 0\\\\\\\
6189 local power = 1\\\\\\\
6190 for i = 1, n do\\\\\\\
6191 rslt = rslt + tbl[i]*power\\\\\\\
6192 power = power*2\\\\\\\
6193 end\\\\\\\
6194 return rslt\\\\\\\
6195end\\\\\\\
6196bit[\\\\\\\"checkint\\\\\\\"] = function(n)\\\\\\\
6197 if(n - math.floor(n) > 0) then\\\\\\\
6198 error(\\\\\\\"trying to use bitwise operation on non-integer!\\\\\\\")\\\\\\\
6199 end\\\\\\\
6200end\\\\\\\
6201bit[\\\\\\\"expand\\\\\\\"] = function(tbl_m, tbl_n)\\\\\\\
6202 local big = {}\\\\\\\
6203 local small = {}\\\\\\\
6204 if(table.getn(tbl_m) > table.getn(tbl_n)) then\\\\\\\
6205 big = tbl_m\\\\\\\
6206 small = tbl_n\\\\\\\
6207 else\\\\\\\
6208 big = tbl_n\\\\\\\
6209 small = tbl_m\\\\\\\
6210 end\\\\\\\
6211 for i = table.getn(small) + 1, table.getn(big) do\\\\\\\
6212 small[i] = 0\\\\\\\
6213 end\\\\\\\
6214end\\\\\\\
6215\\\\\\\
6216local FCS = {}\\\\\\\
6217FCS[\\\\\\\"16\\\\\\\"] = {\\\\\\\
6218 [0]=0, 4489, 8978, 12955, 17956, 22445, 25910, 29887,\\\\\\\
6219 35912, 40385, 44890, 48851, 51820, 56293, 59774, 63735,\\\\\\\
6220 4225, 264, 13203, 8730, 22181, 18220, 30135, 25662,\\\\\\\
6221 40137, 36160, 49115, 44626, 56045, 52068, 63999, 59510,\\\\\\\
6222 8450, 12427, 528, 5017, 26406, 30383, 17460, 21949,\\\\\\\
6223 44362, 48323, 36440, 40913, 60270, 64231, 51324, 55797,\\\\\\\
6224 12675, 8202, 4753, 792, 30631, 26158, 21685, 17724,\\\\\\\
6225 48587, 44098, 40665, 36688, 64495, 60006, 55549, 51572,\\\\\\\
6226 16900, 21389, 24854, 28831, 1056, 5545, 10034, 14011,\\\\\\\
6227 52812, 57285, 60766, 64727, 34920, 39393, 43898, 47859,\\\\\\\
6228 21125, 17164, 29079, 24606, 5281, 1320, 14259, 9786,\\\\\\\
6229 57037, 53060, 64991, 60502, 39145, 35168, 48123, 43634,\\\\\\\
6230 25350, 29327, 16404, 20893, 9506, 13483, 1584, 6073,\\\\\\\
6231 61262, 65223, 52316, 56789, 43370, 47331, 35448, 39921,\\\\\\\
6232 29575, 25102, 20629, 16668, 13731, 9258, 5809, 1848,\\\\\\\
6233 65487, 60998, 56541, 52564, 47595, 43106, 39673, 35696,\\\\\\\
6234 33800, 38273, 42778, 46739, 49708, 54181, 57662, 61623,\\\\\\\
6235 2112, 6601, 11090, 15067, 20068, 24557, 28022, 31999,\\\\\\\
6236 38025, 34048, 47003, 42514, 53933, 49956, 61887, 57398,\\\\\\\
6237 6337, 2376, 15315, 10842, 24293, 20332, 32247, 27774,\\\\\\\
6238 42250, 46211, 34328, 38801, 58158, 62119, 49212, 53685,\\\\\\\
6239 10562, 14539, 2640, 7129, 28518, 32495, 19572, 24061,\\\\\\\
6240 46475, 41986, 38553, 34576, 62383, 57894, 53437, 49460,\\\\\\\
6241 14787, 10314, 6865, 2904, 32743, 28270, 23797, 19836,\\\\\\\
6242 50700, 55173, 58654, 62615, 32808, 37281, 41786, 45747,\\\\\\\
6243 19012, 23501, 26966, 30943, 3168, 7657, 12146, 16123,\\\\\\\
6244 54925, 50948, 62879, 58390, 37033, 33056, 46011, 41522,\\\\\\\
6245 23237, 19276, 31191, 26718, 7393, 3432, 16371, 11898,\\\\\\\
6246 59150, 63111, 50204, 54677, 41258, 45219, 33336, 37809,\\\\\\\
6247 27462, 31439, 18516, 23005, 11618, 15595, 3696, 8185,\\\\\\\
6248 63375, 58886, 54429, 50452, 45483, 40994, 37561, 33584,\\\\\\\
6249 31687, 27214, 22741, 18780, 15843, 11370, 7921, 3960 }\\\\\\\
6250FCS[\\\\\\\"32\\\\\\\"] = {\\\\\\\
6251 [0]=0, 1996959894, -301047508, -1727442502, 124634137, 1886057615, -379345611, -1637575261,\\\\\\\
6252 249268274, 2044508324, -522852066, -1747789432, 162941995, 2125561021, -407360249, -1866523247,\\\\\\\
6253 498536548, 1789927666, -205950648, -2067906082, 450548861, 1843258603, -187386543, -2083289657,\\\\\\\
6254 325883990, 1684777152, -43845254, -1973040660, 335633487, 1661365465, -99664541, -1928851979,\\\\\\\
6255 997073096, 1281953886, -715111964, -1570279054, 1006888145, 1258607687, -770865667, -1526024853,\\\\\\\
6256 901097722, 1119000684, -608450090, -1396901568, 853044451, 1172266101, -589951537, -1412350631,\\\\\\\
6257 651767980, 1373503546, -925412992, -1076862698, 565507253, 1454621731, -809855591, -1195530993,\\\\\\\
6258 671266974, 1594198024, -972236366, -1324619484, 795835527, 1483230225, -1050600021, -1234817731,\\\\\\\
6259 1994146192, 31158534, -1731059524, -271249366, 1907459465, 112637215, -1614814043, -390540237,\\\\\\\
6260 2013776290, 251722036, -1777751922, -519137256, 2137656763, 141376813, -1855689577, -429695999,\\\\\\\
6261 1802195444, 476864866, -2056965928, -228458418, 1812370925, 453092731, -2113342271, -183516073,\\\\\\\
6262 1706088902, 314042704, -1950435094, -54949764, 1658658271, 366619977, -1932296973, -69972891,\\\\\\\
6263 1303535960, 984961486, -1547960204, -725929758, 1256170817, 1037604311, -1529756563, -740887301,\\\\\\\
6264 1131014506, 879679996, -1385723834, -631195440, 1141124467, 855842277, -1442165665, -586318647,\\\\\\\
6265 1342533948, 654459306, -1106571248, -921952122, 1466479909, 544179635, -1184443383, -832445281,\\\\\\\
6266 1591671054, 702138776, -1328506846, -942167884, 1504918807, 783551873, -1212326853, -1061524307,\\\\\\\
6267 -306674912, -1698712650, 62317068, 1957810842, -355121351, -1647151185, 81470997, 1943803523,\\\\\\\
6268 -480048366, -1805370492, 225274430, 2053790376, -468791541, -1828061283, 167816743, 2097651377,\\\\\\\
6269 -267414716, -2029476910, 503444072, 1762050814, -144550051, -2140837941, 426522225, 1852507879,\\\\\\\
6270 -19653770, -1982649376, 282753626, 1742555852, -105259153, -1900089351, 397917763, 1622183637,\\\\\\\
6271 -690576408, -1580100738, 953729732, 1340076626, -776247311, -1497606297, 1068828381, 1219638859,\\\\\\\
6272 -670225446, -1358292148, 906185462, 1090812512, -547295293, -1469587627, 829329135, 1181335161,\\\\\\\
6273 -882789492, -1134132454, 628085408, 1382605366, -871598187, -1156888829, 570562233, 1426400815,\\\\\\\
6274 -977650754, -1296233688, 733239954, 1555261956, -1026031705, -1244606671, 752459403, 1541320221,\\\\\\\
6275 -1687895376, -328994266, 1969922972, 40735498, -1677130071, -351390145, 1913087877, 83908371,\\\\\\\
6276 -1782625662, -491226604, 2075208622, 213261112, -1831694693, -438977011, 2094854071, 198958881,\\\\\\\
6277 -2032938284, -237706686, 1759359992, 534414190, -2118248755, -155638181, 1873836001, 414664567,\\\\\\\
6278 -2012718362, -15766928, 1711684554, 285281116, -1889165569, -127750551, 1634467795, 376229701,\\\\\\\
6279 -1609899400, -686959890, 1308918612, 956543938, -1486412191, -799009033, 1231636301, 1047427035,\\\\\\\
6280 -1362007478, -640263460, 1088359270, 936918000, -1447252397, -558129467, 1202900863, 817233897,\\\\\\\
6281 -1111625188, -893730166, 1404277552, 615818150, -1160759803, -841546093, 1423857449, 601450431,\\\\\\\
6282 -1285129682, -1000256840, 1567103746, 711928724, -1274298825, -1022587231, 1510334235, 755167117 }\\\\\\\
6283\\\\\\\
6284--String Utils :\\\\\\\
6285\\\\\\\
6286function toCharTable(str) --Returns table of @str's chars\\\\\\\
6287 if not str then return nil end\\\\\\\
6288 str = tostring(str)\\\\\\\
6289\\\\009local chars = {}\\\\\\\
6290\\\\009for n=1,#str do\\\\\\\
6291\\\\009\\\\009chars[n] = str:sub(n,n)\\\\\\\
6292\\\\009end\\\\\\\
6293\\\\009return chars\\\\\\\
6294end\\\\\\\
6295\\\\\\\
6296function toByteTable(str) --Returns table of @str's bytes\\\\\\\
6297 if not str then return nil end\\\\\\\
6298 str = tostring(str)\\\\\\\
6299\\\\009local bytes = {}\\\\\\\
6300\\\\009for n=1,#str do\\\\\\\
6301\\\\009\\\\009bytes[n] = str:byte(n)\\\\\\\
6302\\\\009end\\\\\\\
6303\\\\009return bytes\\\\\\\
6304end\\\\\\\
6305\\\\\\\
6306function fromCharTable(chars) --Returns string made of chracters in @chars\\\\\\\
6307 if not chars or type(chars)~=\\\\\\\"table\\\\\\\" then return nil end\\\\\\\
6308\\\\009return table.concat(chars)\\\\\\\
6309end\\\\\\\
6310\\\\\\\
6311function fromByteTable(bytes) --Returns string made of bytes in @bytes\\\\\\\
6312 if not bytes or type(bytes)~=\\\\\\\"table\\\\\\\" then return nil end\\\\\\\
6313\\\\009local str = \\\\\\\"\\\\\\\"\\\\\\\
6314\\\\009for n=1,#bytes do\\\\\\\
6315\\\\009\\\\009str = str..string.char(bytes[n])\\\\\\\
6316\\\\009end\\\\\\\
6317\\\\009return str\\\\\\\
6318end\\\\\\\
6319\\\\\\\
6320function contains(str,find) --Returns true if @str contains @find\\\\\\\
6321 if not str then return nil end\\\\\\\
6322 str = tostring(str)\\\\\\\
6323\\\\009for n=1, #str-#find+1 do\\\\\\\
6324\\\\009\\\\009if str:sub(n,n+#find-1) == find then return true end\\\\\\\
6325\\\\009end\\\\\\\
6326\\\\009return false\\\\\\\
6327end\\\\\\\
6328\\\\\\\
6329function startsWith(str,Start) --Check if @str starts with @Start\\\\\\\
6330 if not str then return nil end\\\\\\\
6331 str = tostring(str)\\\\\\\
6332 return str:sub(1,Start:len())==Start\\\\\\\
6333end\\\\\\\
6334\\\\\\\
6335function endsWith(str,End) --Check if @str ends with @End\\\\\\\
6336 if not str then return nil end\\\\\\\
6337 str = tostring(str)\\\\\\\
6338 return End=='' or str:sub(#str-#End+1)==End\\\\\\\
6339end\\\\\\\
6340\\\\\\\
6341function trim(str) --Trim @str of initial/trailing whitespace\\\\\\\
6342 if not str then return nil end\\\\\\\
6343 str = tostring(str)\\\\\\\
6344 return (str:gsub(\\\\\\\"^%s*(.-)%s*$\\\\\\\", \\\\\\\"%1\\\\\\\"))\\\\\\\
6345end\\\\\\\
6346\\\\\\\
6347function firstLetterUpper(str) --Capitilizes first letter of @str\\\\\\\
6348 if not str then return nil end\\\\\\\
6349 str = tostring(str)\\\\\\\
6350\\\\009str = str:gsub(\\\\\\\"%a\\\\\\\", string.upper, 1)\\\\\\\
6351 return str\\\\\\\
6352end\\\\\\\
6353\\\\\\\
6354function titleCase(str) --Changes @str to title case\\\\\\\
6355\\\\009if not str then return nil end\\\\\\\
6356\\\\009str = tostring(str)\\\\\\\
6357 local function tchelper(first, rest)\\\\\\\
6358\\\\009\\\\009return first:upper()..rest:lower()\\\\\\\
6359 end\\\\\\\
6360 str = str:gsub(\\\\\\\"(%a)([%w_']*)\\\\\\\", tchelper)\\\\\\\
6361\\\\009return str\\\\\\\
6362end\\\\\\\
6363\\\\\\\
6364function isRepetition(str, pat) --Checks if @str is a repetition of @pat\\\\\\\
6365 if not str then return nil end\\\\\\\
6366 str = tostring(str)\\\\\\\
6367\\\\009return \\\\\\\"\\\\\\\" == str:gsub(pat, \\\\\\\"\\\\\\\")\\\\\\\
6368end\\\\\\\
6369\\\\\\\
6370function isRepetitionWS(str, pat) --Checks if @str is a repetition of @pat seperated by whitespaces\\\\\\\
6371 if not str then return nil end\\\\\\\
6372 str = tostring(str)\\\\\\\
6373\\\\009return not str:gsub(pat, \\\\\\\"\\\\\\\"):find\\\\\\\"%S\\\\\\\"\\\\\\\
6374end\\\\\\\
6375\\\\\\\
6376function urlDecode(str) --Url decodes @str\\\\\\\
6377 if not str then return nil end\\\\\\\
6378 str = tostring(str)\\\\\\\
6379\\\\009str = string.gsub (str, \\\\\\\"+\\\\\\\", \\\\\\\" \\\\\\\")\\\\\\\
6380\\\\009str = string.gsub (str, \\\\\\\"%%(%x%x)\\\\\\\", function(h) return string.char(tonumber(h,16)) end)\\\\\\\
6381\\\\009str = string.gsub (str, \\\\\\\"\\\\\\\\r\\\\\\\\n\\\\\\\", \\\\\\\"\\\\\\\\n\\\\\\\")\\\\\\\
6382\\\\009return str\\\\\\\
6383end\\\\\\\
6384\\\\\\\
6385function urlEncode(str) --Url encodes @str\\\\\\\
6386 if not str then return nil end\\\\\\\
6387 str = tostring(str)\\\\\\\
6388\\\\009if (str) then\\\\\\\
6389\\\\009\\\\009str = string.gsub (str, \\\\\\\"\\\\\\\\n\\\\\\\", \\\\\\\"\\\\\\\\r\\\\\\\\n\\\\\\\")\\\\\\\
6390\\\\009\\\\009str = string.gsub (str, \\\\\\\"([^%w ])\\\\\\\", function (c) return string.format (\\\\\\\"%%%02X\\\\\\\", string.byte(c)) end)\\\\\\\
6391\\\\009\\\\009str = string.gsub (str, \\\\\\\" \\\\\\\", \\\\\\\"+\\\\\\\")\\\\\\\
6392\\\\009end\\\\\\\
6393\\\\009return str\\\\\\\
6394end\\\\\\\
6395\\\\\\\
6396function isEmailAddress(str) --Checks if @str is a valid email address\\\\\\\
6397 if not str then return nil end\\\\\\\
6398 str = tostring(str)\\\\\\\
6399\\\\009if (str:match(\\\\\\\"[A-Za-z0-9%.%%%+%-]+@[A-Za-z0-9%.%%%+%-]+%.%w%w%w?%w?\\\\\\\")) then\\\\\\\
6400\\\\009\\\\009return true\\\\\\\
6401\\\\009else\\\\\\\
6402\\\\009\\\\009return false\\\\\\\
6403\\\\009end\\\\\\\
6404end\\\\\\\
6405\\\\\\\
6406function chunk(str, size) --Splits @str into chunks of length @size\\\\\\\
6407\\\\009if not size then return nil end\\\\\\\
6408\\\\009str = tostring(str)\\\\\\\
6409\\\\009local num2App = size - (#str%size)\\\\\\\
6410\\\\009str = str..(rep(char(0), num2App) or \\\\\\\"\\\\\\\")\\\\\\\
6411\\\\009assert(#str%size==0)\\\\\\\
6412\\\\009local chunks = {}\\\\\\\
6413\\\\009local numChunks = #str / size\\\\\\\
6414\\\\009local chunk = 0\\\\\\\
6415\\\\009while chunk < numChunks do\\\\\\\
6416\\\\009\\\\009local start = chunk * size + 1\\\\\\\
6417 chunk = chunk+1\\\\\\\
6418\\\\009\\\\009if start+size-1 > #str-num2App then\\\\\\\
6419 if str:sub(start, #str-num2App) ~= (nil or \\\\\\\"\\\\\\\") then\\\\\\\
6420\\\\009\\\\009\\\\009 chunks[chunk] = str:sub(start, #str-num2App)\\\\\\\
6421 end\\\\\\\
6422\\\\009\\\\009else\\\\\\\
6423\\\\009\\\\009\\\\009chunks[chunk] = str:sub(start, start+size-1)\\\\\\\
6424\\\\009\\\\009end\\\\\\\
6425\\\\009end\\\\\\\
6426\\\\009return chunks\\\\\\\
6427end\\\\\\\
6428\\\\\\\
6429function find(str, match, startIndex) --Finds @match in @str optionally after @startIndex\\\\\\\
6430\\\\009if not match then return nil end\\\\\\\
6431\\\\009str = tostring(str)\\\\\\\
6432\\\\009local _ = startIndex or 1\\\\\\\
6433\\\\009local _s = nil\\\\\\\
6434\\\\009local _e = nil\\\\\\\
6435\\\\009local _len = match:len()\\\\\\\
6436\\\\009while true do\\\\\\\
6437\\\\009\\\\009local _t = str:sub( _ , _len + _ - 1)\\\\\\\
6438\\\\009\\\\009if _t == match then\\\\\\\
6439\\\\009\\\\009\\\\009_s = _\\\\\\\
6440\\\\009\\\\009\\\\009_e = _ + _len - 1\\\\\\\
6441\\\\009\\\\009\\\\009break\\\\\\\
6442\\\\009\\\\009end\\\\\\\
6443\\\\009\\\\009_ = _ + 1\\\\\\\
6444\\\\009\\\\009if _ > str:len() then break end\\\\\\\
6445\\\\009end\\\\\\\
6446\\\\009if _s == nil then return nil else return _s, _e end\\\\\\\
6447end\\\\\\\
6448\\\\\\\
6449function separate(str, divider) --Separates @str on @divider\\\\\\\
6450\\\\009if not divider then return nil end\\\\\\\
6451\\\\009str = tostring(str)\\\\\\\
6452\\\\009local start = {}\\\\\\\
6453\\\\009local endS = {}\\\\\\\
6454\\\\009local n=1\\\\\\\
6455\\\\009repeat\\\\\\\
6456\\\\009\\\\009if n==1 then\\\\\\\
6457\\\\009\\\\009\\\\009start[n], endS[n] = find(str, divider)\\\\\\\
6458\\\\009\\\\009else\\\\\\\
6459\\\\009\\\\009\\\\009start[n], endS[n] = find(str, divider, endS[n-1]+1)\\\\\\\
6460 end\\\\\\\
6461\\\\009\\\\009n=n+1\\\\\\\
6462\\\\009until start[n-1]==nil\\\\\\\
6463\\\\009local subs = {}\\\\\\\
6464\\\\009for n=1, #start+1 do\\\\\\\
6465\\\\009\\\\009if n==1 then\\\\\\\
6466\\\\009\\\\009\\\\009subs[n] = str:sub(1, start[n]-1)\\\\\\\
6467\\\\009\\\\009elseif n==#start+1 then\\\\\\\
6468\\\\009\\\\009\\\\009subs[n] = str:sub(endS[n-1]+1)\\\\\\\
6469\\\\009\\\\009else\\\\\\\
6470\\\\009\\\\009\\\\009subs[n] = str:sub(endS[n-1]+1, start[n]-1)\\\\\\\
6471 end\\\\\\\
6472\\\\009end\\\\\\\
6473\\\\009return subs\\\\\\\
6474end\\\\\\\
6475\\\\\\\
6476function replace(str, from, to) --Replaces @from to @to in @str\\\\\\\
6477\\\\009if not from then return nil end\\\\\\\
6478\\\\009str = tostring(str)\\\\\\\
6479\\\\009local pcs = seperate(str, from)\\\\\\\
6480\\\\009str = pcs[1]\\\\\\\
6481\\\\009for n=2,#pcs do\\\\\\\
6482\\\\009\\\\009str = str..to..pcs[n]\\\\\\\
6483\\\\009end\\\\\\\
6484\\\\009return str\\\\\\\
6485end\\\\\\\
6486\\\\\\\
6487function jumble(str) --Jumbles @str\\\\\\\
6488\\\\009if not str then return nil end\\\\\\\
6489\\\\009str = tostring(str)\\\\\\\
6490\\\\009local chars = {}\\\\\\\
6491\\\\009for i = 1, #str do\\\\\\\
6492\\\\009\\\\009chars[i] = str:sub(i, i)\\\\\\\
6493\\\\009end\\\\\\\
6494\\\\009local usedNums = \\\\\\\":\\\\\\\"\\\\\\\
6495\\\\009local res = \\\\\\\"\\\\\\\"\\\\\\\
6496\\\\009local rand = 0\\\\\\\
6497\\\\009for i=1, #chars do\\\\\\\
6498\\\\009\\\\009while true do\\\\\\\
6499\\\\009\\\\009\\\\009rand = math.random(#chars)\\\\\\\
6500\\\\009\\\\009\\\\009if find(usedNums, \\\\\\\":\\\\\\\"..rand..\\\\\\\":\\\\\\\") == nil then break end\\\\\\\
6501\\\\009\\\\009end\\\\\\\
6502\\\\009\\\\009res = res..chars[rand]\\\\\\\
6503\\\\009\\\\009usedNums = usedNums..rand..\\\\\\\":\\\\\\\"\\\\\\\
6504\\\\009end\\\\\\\
6505\\\\009return res\\\\\\\
6506end\\\\\\\
6507\\\\\\\
6508function toBase(str, base) --Encodes @str in @base\\\\\\\
6509\\\\009if not base then return nil end\\\\\\\
6510\\\\009str = tostring(str)\\\\\\\
6511\\\\009local res = \\\\\\\"\\\\\\\"\\\\\\\
6512\\\\009for i = 1, str:len() do\\\\\\\
6513\\\\009\\\\009if i == 1 then\\\\\\\
6514\\\\009\\\\009\\\\009res = basen(str:byte(i), base)\\\\\\\
6515\\\\009\\\\009else\\\\\\\
6516\\\\009\\\\009\\\\009res = res..\\\\\\\":\\\\\\\"..basen(str:byte(i), base)\\\\\\\
6517\\\\009\\\\009end\\\\\\\
6518\\\\009end\\\\\\\
6519\\\\009return res\\\\\\\
6520end\\\\\\\
6521\\\\\\\
6522function fromBase(str, base) --Decodes @str from @base\\\\\\\
6523\\\\009if not base then return nil end\\\\\\\
6524\\\\009str = tostring(str)\\\\\\\
6525\\\\009local bytes = seperate(str, \\\\\\\":\\\\\\\")\\\\\\\
6526\\\\009local res = \\\\\\\"\\\\\\\"\\\\\\\
6527\\\\009for i = 1, #bytes do\\\\\\\
6528\\\\009\\\\009res = res..(string.char(basen(tonumber(bytes[i], base), 10)))\\\\\\\
6529\\\\009end\\\\\\\
6530\\\\009return res\\\\\\\
6531end\\\\\\\
6532\\\\\\\
6533function toBinary(str) --Encodes @str in binary\\\\\\\
6534\\\\009if not str then return nil end\\\\\\\
6535\\\\009str = tostring(str)\\\\\\\
6536\\\\009return toBase(str, 2)\\\\\\\
6537end\\\\\\\
6538\\\\\\\
6539function fromBinary(str) --Decodes @str from binary\\\\\\\
6540\\\\009if not str then return nil end\\\\\\\
6541\\\\009str = tostring(str)\\\\\\\
6542\\\\009return fromBase(str, 2)\\\\\\\
6543end\\\\\\\
6544\\\\\\\
6545function toOctal(str) --Encodes @str in octal\\\\\\\
6546\\\\009if not str then return nil end\\\\\\\
6547\\\\009str = tostring(str)\\\\\\\
6548\\\\009return toBase(str, 8)\\\\\\\
6549end\\\\\\\
6550\\\\\\\
6551function fromOctal(str) --Decodes @str from octal\\\\\\\
6552\\\\009if not str then return nil end\\\\\\\
6553\\\\009str = tostring(str)\\\\\\\
6554\\\\009return fromBase(str, 8)\\\\\\\
6555end\\\\\\\
6556\\\\\\\
6557function toHex(str) --Encodes @str in hex\\\\\\\
6558\\\\009if not str then return nil end\\\\\\\
6559\\\\009str = tostring(str)\\\\\\\
6560\\\\009return toBase(str, 16)\\\\\\\
6561end\\\\\\\
6562\\\\\\\
6563function fromHex(str) --Decodes @str from hex\\\\\\\
6564\\\\009if not str then return nil end\\\\\\\
6565\\\\009str = tostring(str)\\\\\\\
6566\\\\009return fromBase(str, 16)\\\\\\\
6567end\\\\\\\
6568\\\\\\\
6569function toBase36(str) --Encodes @str in Base36\\\\\\\
6570\\\\009if not str then return nil end\\\\\\\
6571\\\\009str = tostring(str)\\\\\\\
6572\\\\009return toBase(str, 36)\\\\\\\
6573end\\\\\\\
6574\\\\\\\
6575function fromBase36(str) --Decodes @str from Base36\\\\\\\
6576\\\\009if not str then return nil end\\\\\\\
6577\\\\009str = tostring(str)\\\\\\\
6578\\\\009return fromBase(str, 36)\\\\\\\
6579end\\\\\\\
6580\\\\\\\
6581function toBase32(str) --Encodes @str in Base32\\\\\\\
6582\\\\009if not str then return nil end\\\\\\\
6583\\\\009str = tostring(str)\\\\\\\
6584\\\\009local byte=0\\\\\\\
6585\\\\009local bits=0\\\\\\\
6586\\\\009local rez=\\\\\\\"\\\\\\\"\\\\\\\
6587\\\\009local i=0\\\\\\\
6588\\\\009for i = 1, str:len() do\\\\\\\
6589\\\\009\\\\009byte=byte*256+str:byte(i)\\\\\\\
6590\\\\009\\\\009bits=bits+8\\\\\\\
6591\\\\009\\\\009repeat\\\\\\\
6592\\\\009\\\\009\\\\009bits=bits-5\\\\\\\
6593\\\\009\\\\009\\\\009local mul=(2^(bits))\\\\\\\
6594\\\\009\\\\009\\\\009local b32n=math.floor(byte/mul)\\\\\\\
6595\\\\009\\\\009\\\\009byte=byte-(b32n*mul)\\\\\\\
6596\\\\009\\\\009\\\\009b32n=b32n+1\\\\\\\
6597\\\\009\\\\009\\\\009rez=rez..string.sub(base32,b32n,b32n)\\\\\\\
6598\\\\009\\\\009until bits<5\\\\\\\
6599\\\\009end\\\\\\\
6600\\\\009if bits>0 then\\\\\\\
6601\\\\009\\\\009local b32n= math.fmod(byte*(2^(5-bits)),32)\\\\\\\
6602\\\\009\\\\009b32n=b32n+1\\\\\\\
6603\\\\009\\\\009rez=rez..string.sub(base32,b32n,b32n)\\\\\\\
6604\\\\009end\\\\\\\
6605\\\\009return rez\\\\\\\
6606end\\\\\\\
6607\\\\\\\
6608function fromBase32(str) --Decodes @str from Base32\\\\\\\
6609\\\\009if not str then return nil end\\\\\\\
6610\\\\009str = tostring(str)\\\\\\\
6611\\\\009local b32n=0\\\\\\\
6612\\\\009local bits=0\\\\\\\
6613\\\\009local rez=\\\\\\\"\\\\\\\"\\\\\\\
6614\\\\009local i=0\\\\\\\
6615\\\\009string.gsub(str:upper(), \\\\\\\"[\\\\\\\"..base32..\\\\\\\"]\\\\\\\", function (char)\\\\\\\
6616\\\\009\\\\009local num = string.find(base32, char, 1, true)\\\\\\\
6617\\\\009\\\\009b32n=b32n*32+(num - 1)\\\\\\\
6618\\\\009\\\\009bits=bits+5\\\\\\\
6619\\\\009\\\\009while bits>=8 do\\\\\\\
6620\\\\009\\\\009\\\\009bits=bits-8\\\\\\\
6621\\\\009\\\\009\\\\009local mul=(2^(bits))\\\\\\\
6622\\\\009\\\\009\\\\009local byte = math.floor(b32n/mul)\\\\\\\
6623\\\\009\\\\009\\\\009b32n=b32n-(byte*mul)\\\\\\\
6624\\\\009\\\\009\\\\009rez=rez..string.char(byte)\\\\\\\
6625\\\\009\\\\009end\\\\\\\
6626\\\\009end)\\\\\\\
6627\\\\009return rez\\\\\\\
6628end\\\\\\\
6629\\\\\\\
6630function toBase64(str) --Encodes @str in Base64\\\\\\\
6631\\\\009if not str then return nil end\\\\\\\
6632\\\\009str = tostring(str)\\\\\\\
6633\\\\009local bytes = {}\\\\\\\
6634\\\\009local result = \\\\\\\"\\\\\\\"\\\\\\\
6635\\\\009for spos=0,str:len()-1,3 do\\\\\\\
6636\\\\009\\\\009for byte=1,3 do bytes[byte] = str:byte(spos+byte) or 0 end\\\\\\\
6637\\\\009\\\\009result = string.format('%s%s%s%s%s',result,Base64.base64chars[Base64.rsh(bytes[1],2)],Base64.base64chars[Base64.lor(Base64.lsh((bytes[1] % 4),4), Base64.rsh(bytes[2],4))] or \\\\\\\"=\\\\\\\",((str:len()-spos) > 1) and Base64.base64chars[Base64.lor(Base64.lsh(bytes[2] % 16,2), Base64.rsh(bytes[3],6))] or \\\\\\\"=\\\\\\\",((str:len()-spos) > 2) and Base64.base64chars[(bytes[3] % 64)] or \\\\\\\"=\\\\\\\")\\\\\\\
6638\\\\009end\\\\\\\
6639\\\\009return result\\\\\\\
6640end\\\\\\\
6641\\\\\\\
6642function fromBase64(str) --Decodes @str from Base64\\\\\\\
6643\\\\009if not str then return nil end\\\\\\\
6644\\\\009str = tostring(str)\\\\\\\
6645\\\\009local chars = {}\\\\\\\
6646\\\\009local result=\\\\\\\"\\\\\\\"\\\\\\\
6647\\\\009for dpos=0,str:len()-1,4 do\\\\\\\
6648\\\\009\\\\009for char=1,4 do chars[char] = Base64.base64bytes[(str:sub((dpos+char),(dpos+char)) or \\\\\\\"=\\\\\\\")] end\\\\\\\
6649\\\\009\\\\009result = string.format('%s%s%s%s',result,string.char(Base64.lor(Base64.lsh(chars[1],2), Base64.rsh(chars[2],4))),(chars[3] ~= nil) and string.char(Base64.lor(Base64.lsh(chars[2],4), Base64.rsh(chars[3],2))) or \\\\\\\"\\\\\\\",(chars[4] ~= nil) and string.char(Base64.lor(Base64.lsh(chars[3],6) % 192, (chars[4]))) or \\\\\\\"\\\\\\\")\\\\\\\
6650\\\\009end\\\\\\\
6651\\\\009return result\\\\\\\
6652end\\\\\\\
6653\\\\\\\
6654function rot13(str) --Rot13s @str\\\\\\\
6655\\\\009if not str then return nil end\\\\\\\
6656\\\\009str = tostring(str)\\\\\\\
6657\\\\009local rot = \\\\\\\"\\\\\\\"\\\\\\\
6658\\\\009local len = str:len()\\\\\\\
6659\\\\009for i = 1, len do\\\\\\\
6660\\\\009\\\\009local k = str:byte(i)\\\\\\\
6661\\\\009\\\\009if (k >= 65 and k <= 77) or (k >= 97 and k <=109) then\\\\\\\
6662\\\\009\\\\009\\\\009rot = rot..string.char(k+13)\\\\\\\
6663\\\\009\\\\009elseif (k >= 78 and k <= 90) or (k >= 110 and k <= 122) then\\\\\\\
6664\\\\009\\\\009\\\\009rot = rot..string.char(k-13)\\\\\\\
6665\\\\009\\\\009else\\\\\\\
6666\\\\009\\\\009\\\\009rot = rot..string.char(k)\\\\\\\
6667\\\\009\\\\009end\\\\\\\
6668\\\\009end\\\\\\\
6669\\\\009return rot\\\\\\\
6670end\\\\\\\
6671\\\\\\\
6672function rot47(str) --Rot47s @str\\\\\\\
6673\\\\009if not str then return nil end\\\\\\\
6674\\\\009str = tostring(str)\\\\\\\
6675\\\\009local rot = \\\\\\\"\\\\\\\"\\\\\\\
6676\\\\009for i = 1, str:len() do\\\\\\\
6677\\\\009\\\\009local p = str:byte(i)\\\\\\\
6678\\\\009\\\\009if p >= string.byte('!') and p <= string.byte('O') then\\\\\\\
6679\\\\009\\\\009\\\\009p = ((p + 47) % 127)\\\\\\\
6680\\\\009\\\\009elseif p >= string.byte('P') and p <= string.byte('~') then\\\\\\\
6681\\\\009\\\\009\\\\009p = ((p - 47) % 127)\\\\\\\
6682\\\\009\\\\009end\\\\\\\
6683\\\\009\\\\009rot = rot..string.char(p)\\\\\\\
6684\\\\009end\\\\\\\
6685\\\\009return rot\\\\\\\
6686end\\\\\\\
6687\\\\\\\
6688function SHA1(str) --Returns SHA1 Hash of @str\\\\\\\
6689 if not str then return nil end\\\\\\\
6690 str = tostring(str)\\\\\\\
6691 local H0,H1,H2,H3,H4 = 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0\\\\\\\
6692 local msg_len_in_bits = #str * 8\\\\\\\
6693 local first_append = char(0x80)\\\\\\\
6694 local non_zero_message_bytes = #str +1 +8\\\\\\\
6695 local current_mod = non_zero_message_bytes % 64\\\\\\\
6696 local second_append = current_mod>0 and rep(char(0), 64 - current_mod) or \\\\\\\"\\\\\\\"\\\\\\\
6697 local B1, R1 = modf(msg_len_in_bits / 0x01000000)\\\\\\\
6698 local B2, R2 = modf( 0x01000000 * R1 / 0x00010000)\\\\\\\
6699 local B3, R3 = modf( 0x00010000 * R2 / 0x00000100)\\\\\\\
6700 local B4\\\\009 =\\\\0090x00000100 * R3\\\\\\\
6701 local L64 = char( 0) .. char( 0) .. char( 0) .. char( 0)\\\\\\\
6702 .. char(B1) .. char(B2) .. char(B3) .. char(B4)\\\\\\\
6703 str = str .. first_append .. second_append .. L64\\\\\\\
6704 assert(#str % 64 == 0)\\\\\\\
6705 local chunks = #str / 64\\\\\\\
6706 local W = { }\\\\\\\
6707 local start, A, B, C, D, E, f, K, TEMP\\\\\\\
6708 local chunk = 0\\\\\\\
6709 while chunk < chunks do\\\\\\\
6710 start,chunk = chunk * 64 + 1,chunk + 1\\\\\\\
6711 for t = 0, 15 do\\\\\\\
6712 W[t] = tSHA1.bytes_to_w32(str:byte(start, start + 3))\\\\\\\
6713 start = start + 4\\\\\\\
6714 end\\\\\\\
6715 for t = 16, 79 do\\\\\\\
6716 W[t] = tSHA1.w32_rot(1, tSHA1.w32_xor_n(W[t-3], W[t-8], W[t-14], W[t-16]))\\\\\\\
6717 end\\\\\\\
6718 A,B,C,D,E = H0,H1,H2,H3,H4\\\\\\\
6719 for t = 0, 79 do\\\\\\\
6720 if t <= 19 then\\\\\\\
6721 f = tSHA1.w32_or(tSHA1.w32_and(B, C), tSHA1.w32_and(tSHA1.w32_not(B), D))\\\\\\\
6722 K = 0x5A827999\\\\\\\
6723 elseif t <= 39 then\\\\\\\
6724 f = tSHA1.w32_xor_n(B, C, D)\\\\\\\
6725 K = 0x6ED9EBA1\\\\\\\
6726 elseif t <= 59 then\\\\\\\
6727 f = tSHA1.w32_or3(tSHA1.w32_and(B, C), tSHA1.w32_and(B, D), tSHA1.w32_and(C, D))\\\\\\\
6728 K = 0x8F1BBCDC\\\\\\\
6729 else\\\\\\\
6730 f = tSHA1.w32_xor_n(B, C, D)\\\\\\\
6731 K = 0xCA62C1D6\\\\\\\
6732 end\\\\\\\
6733 A,B,C,D,E = tSHA1.w32_add_n(tSHA1.w32_rot(5, A), f, E, W[t], K),\\\\\\\
6734 A, tSHA1.w32_rot(30, B), C, D\\\\\\\
6735 end\\\\\\\
6736 H0,H1,H2,H3,H4 = tSHA1.w32_add(H0, A),tSHA1.w32_add(H1, B),tSHA1.w32_add(H2, C),tSHA1.w32_add(H3, D),tSHA1.w32_add(H4, E)\\\\\\\
6737 end\\\\\\\
6738 local f = tSHA1.w32_to_hexstring\\\\\\\
6739 return f(H0) .. f(H1) .. f(H2) .. f(H3) .. f(H4)\\\\\\\
6740end\\\\\\\
6741\\\\\\\
6742function CRC32(str) --Returns CRC32 Hash of @str\\\\\\\
6743 local crc, l, i = 0xFFFFFFFF, string.len(str)\\\\\\\
6744 for i = 1, l, 1 do\\\\\\\
6745 crc = bit.bxor(bit.brshift(crc, 8), CRC.crc32[bit.band(bit.bxor(crc, string.byte(str, i)), 0xFF) + 1])\\\\\\\
6746 end\\\\\\\
6747 return bit.bxor(crc, -1)\\\\\\\
6748end\\\\\\\
6749\\\\\\\
6750function FCS16(str) --Returns FCS16 Hash of @str\\\\\\\
6751 local i\\\\\\\
6752 local l=string.len(str)\\\\\\\
6753 local uFcs16 = 65535\\\\\\\
6754 for i = 1,l do\\\\\\\
6755 uFcs16 = bit.bxor(bit.brshift(uFcs16,8), FCS[\\\\\\\"16\\\\\\\"][bit.band(bit.bxor(uFcs16, string.byte(str,i)), 255)])\\\\\\\
6756 end\\\\\\\
6757 return bit.bxor(uFcs16, 65535)\\\\\\\
6758end\\\\\\\
6759\\\\\\\
6760function FCS32(str) --Returns FCS32 Hash of @str\\\\\\\
6761 local i\\\\\\\
6762 local l = string.len(str)\\\\\\\
6763 local uFcs32 = -1\\\\\\\
6764 for i=1,l do\\\\\\\
6765 uFcs32 = bit.bxor(bit.brshift(uFcs32,8), FCS[\\\\\\\"32\\\\\\\"][bit.band(bit.bxor(uFcs32, string.byte(str,i)), 255)])\\\\\\\
6766 end\\\\\\\
6767 return bit.bnot(uFcs32)\\\\\\\
6768end\\\\\\\
6769\\\\\\\
6770function encrypt(str, key) --Encrypts @str with @key\\\\\\\
6771\\\\009if not key then return nil end\\\\\\\
6772\\\\009str = tostring(str)\\\\\\\
6773\\\\009local alphabet = \\\\\\\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\\\\]^_abcdefghijklmnopqrstuvwxyz{|}~\\\\\\\"\\\\\\\
6774\\\\009local _rand = math.random(#alphabet-10)\\\\\\\
6775\\\\009local iv = string.sub(jumble(alphabet), _rand, _rand + 9)\\\\\\\
6776\\\\009iv = jumble(iv)\\\\\\\
6777\\\\009str = iv..str\\\\\\\
6778\\\\009local key = SHA1(key)\\\\\\\
6779\\\\009local strLen = str:len()\\\\\\\
6780\\\\009local keyLen = key:len()\\\\\\\
6781\\\\009local j=1\\\\\\\
6782\\\\009local result = \\\\\\\"\\\\\\\"\\\\\\\
6783\\\\009for i=1, strLen do\\\\\\\
6784\\\\009\\\\009local ordStr = string.byte(str:sub(i,i))\\\\\\\
6785\\\\009\\\\009if j == keyLen then j=1 end\\\\\\\
6786\\\\009\\\\009local ordKey = string.byte(key:sub(j,j))\\\\\\\
6787\\\\009\\\\009result = result..string.reverse(basen(ordStr+ordKey, 36))\\\\\\\
6788\\\\009\\\\009j = j+1\\\\\\\
6789\\\\009end\\\\\\\
6790\\\\009return result\\\\\\\
6791end\\\\\\\
6792\\\\\\\
6793function decrypt(str, key) --Decrypts @str with @key\\\\\\\
6794\\\\009if not key then return nil end\\\\\\\
6795\\\\009str = tostring(str)\\\\\\\
6796\\\\009local key = SHA1(key)\\\\\\\
6797\\\\009local strLen = str:len()\\\\\\\
6798\\\\009local keyLen = key:len()\\\\\\\
6799\\\\009local j=1\\\\\\\
6800\\\\009local result = \\\\\\\"\\\\\\\"\\\\\\\
6801\\\\009for i=1, strLen, 2 do\\\\\\\
6802\\\\009\\\\009local ordStr = basen(tonumber(string.reverse(str:sub(i, i+1)),36),10)\\\\\\\
6803\\\\009\\\\009if j==keyLen then j=1 end\\\\\\\
6804\\\\009\\\\009local ordKey = string.byte(key:sub(j,j))\\\\\\\
6805\\\\009\\\\009result = result..string.char(ordStr-ordKey)\\\\\\\
6806\\\\009\\\\009j = j+1\\\\\\\
6807\\\\009end\\\\\\\
6808\\\\009return result:sub(11)\\\\\\\
6809end\\\\\\\
6810\\\\\\\
6811function setRandSeed(seed) --Sets random seed to @seed\\\\\\\
6812\\\\009math.randomseed(seed)\\\\\\\
6813end\\\\\\\
6814\\\\\\\
6815\\\\\\\
6816--\\\\\\\
6817-- MODIFIED CODE FROM TESSERACT LIES BELOW. \\\\\\\
6818--\\\\\\\
6819\\\\\\\
6820\\\\\\\
6821function traverseKey(array, text)\\\\\\\
6822 for k,v in pairs(array) do\\\\\\\
6823 if v == text then\\\\\\\
6824 return true, k\\\\\\\
6825 end\\\\\\\
6826 end\\\\\\\
6827 return false, nil\\\\\\\
6828end\\\\\\\
6829\\\\\\\
6830function traverseValue(array, text)\\\\\\\
6831 for k,v in pairs(array) do\\\\\\\
6832 if k == text then\\\\\\\
6833 return true, v\\\\\\\
6834 end\\\\\\\
6835 end\\\\\\\
6836 return false, nil\\\\\\\
6837end\\\\\\\
6838\\\\\\\
6839function findKey(array, text)\\\\\\\
6840 for k,v in pairs(array) do\\\\\\\
6841 if k == text then\\\\\\\
6842 return true, k\\\\\\\
6843 end\\\\\\\
6844 end\\\\\\\
6845 return false, nil\\\\\\\
6846end\\\\\\\
6847\\\\\\\
6848function findValue(array, text)\\\\\\\
6849 for k,v in pairs(array) do\\\\\\\
6850 if v == text then\\\\\\\
6851 return true, v\\\\\\\
6852 end\\\\\\\
6853 end\\\\\\\
6854 return false, nil\\\\\\\
6855end\\\\\\\
6856\\\\\\\
6857function queryKey(array, text)\\\\\\\
6858 for k,v in pairs(array) do\\\\\\\
6859 if string.find(k, text) then\\\\\\\
6860 return true, k\\\\\\\
6861 end\\\\\\\
6862 end\\\\\\\
6863 return false, nil\\\\\\\
6864end\\\\\\\
6865\\\\\\\
6866function queryValue(array, text)\\\\\\\
6867 for k,v in pairs(array) do\\\\\\\
6868 if string.find(v, text) then\\\\\\\
6869 return true, v\\\\\\\
6870 end\\\\\\\
6871 end\\\\\\\
6872 return false, nil\\\\\\\
6873end\\\\\\\
6874\\\\\\\
6875function iterateFileLines(path)\\\\\\\
6876 if not fs.exists(path) then return nil end\\\\\\\
6877 local handle = fs.open(path, fs.AF_READ)\\\\\\\
6878 local commands = {}\\\\\\\
6879 local line = handle.readLine()\\\\\\\
6880 while line do\\\\\\\
6881 commands[#commands + 1] = line\\\\\\\
6882 line = handle.readLine()\\\\\\\
6883 end\\\\\\\
6884 handle.close()\\\\\\\
6885 return commands\\\\\\\
6886end\\\\\\\
6887\\\\\\\
6888function readFile(path)\\\\\\\
6889 if not fs.exists(path) then return nil end\\\\\\\
6890 local handle = fs.open(path, fs.AF_READ)\\\\\\\
6891 local content = handle.readAll()\\\\\\\
6892 handle.close()\\\\\\\
6893 return content\\\\\\\
6894end\\\\\\\
6895\\\\\\\
6896function cload(path)\\\\\\\
6897 if fs.exists(path) and not fs.isDir(path) then\\\\\\\
6898 local lf = fs.open(path, \\\\\\\"r\\\\\\\")\\\\\\\
6899 local contents = lf.readAll()\\\\\\\
6900 lf.close()\\\\\\\
6901 return textutils.unserialize(contents)\\\\\\\
6902 else\\\\\\\
6903 return nil\\\\\\\
6904 end\\\\\\\
6905end\\\\\\\
6906\\\\\\\
6907function csave(cTable, path)\\\\\\\
6908 if fs.exists(path) then\\\\\\\
6909 if fs.isDir(path) then\\\\\\\
6910 return false\\\\\\\
6911 end\\\\\\\
6912 end\\\\\\\
6913 local sf = fs.open(path, \\\\\\\"w\\\\\\\")\\\\\\\
6914 sf.write(textutils.serialize(cTable))\\\\\\\
6915 sf.close()\\\\\\\
6916 return true\\\\\\\
6917end\\\\\\\
6918]]\\\\\\\
6919persist(\\\\\\\"stdlib\\\\\\\", libcode)\\\\\\\
6920\\\\\\\
6921return 1\\\"\",\
6922 \"F:libuser.2.so\",\
6923 \"\\\"local libcode = [[\\\\\\\
6924CONSTANT_LINE = \\\\\\\"---------------------------------------------------\\\\\\\"\\\\\\\
6925\\\\\\\
6926--MenuAPI functions (mprint, drawBootMenu) by 1Ridav and MelnikovSM\\\\\\\
6927--Context menu provided generously by MasonCipher\\\\\\\
6928local function mprint(array, this, s1, s2, x, y)\\\\\\\
6929 local c = term.getTextColor()\\\\\\\
6930 term.setTextColor(colors.lightGray)\\\\\\\
6931 for i = 1, #array do\\\\\\\
6932 term.setCursorPos(x, y)\\\\\\\
6933 --Check if option selected\\\\\\\
6934 if i == this then \\\\\\\
6935 --Option selected \\\\\\\
6936 write(s1)\\\\\\\
6937 else \\\\\\\
6938 --Option NOT selected\\\\\\\
6939 write(s2)\\\\\\\
6940 end\\\\\\\
6941 --Print the string\\\\\\\
6942 print(array[i])\\\\\\\
6943 y = y + 1 \\\\\\\
6944 end\\\\\\\
6945 term.setTextColor(c)\\\\\\\
6946end\\\\\\\
6947\\\\\\\
6948local function stdoutg(text, bg, fg)\\\\\\\
6949 local a = term.getBackgroundColor()\\\\\\\
6950 local b = term.getTextColor()\\\\\\\
6951 term.setBackgroundColor(bg or colors.black)\\\\\\\
6952 term.setTextColor(fg or colors.white)\\\\\\\
6953 write(text)\\\\\\\
6954 term.setBackgroundColor(a)\\\\\\\
6955 term.setTextColor(b)\\\\\\\
6956end\\\\\\\
6957\\\\\\\
6958function clearScreen(color)\\\\\\\
6959 term.setBackgroundColor(color or colors.black)\\\\\\\
6960 term.clear()\\\\\\\
6961 term.setCursorPos(1,1)\\\\\\\
6962end\\\\\\\
6963\\\\\\\
6964function button(text, x1, x2, y)\\\\\\\
6965 term.setCursorPos(x1, y)\\\\\\\
6966 print(text)\\\\\\\
6967 local a, b, xx, yy = os.pullEvent(\\\\\\\"mouse_click\\\\\\\")\\\\\\\
6968 if (xx >= x1 and xx <= x2 and yy == y) then\\\\\\\
6969 return true\\\\\\\
6970 else\\\\\\\
6971 return false\\\\\\\
6972 end\\\\\\\
6973end\\\\\\\
6974\\\\\\\
6975function counter(text, y)\\\\\\\
6976 for i=1,100 do\\\\\\\
6977 sleep(0.1)\\\\\\\
6978 term.setCursorPos(1, y)\\\\\\\
6979 print(text..\\\\\\\" [\\\\\\\"..tostring(i)..\\\\\\\"%]\\\\\\\")\\\\\\\
6980 end\\\\\\\
6981end\\\\\\\
6982\\\\\\\
6983function drawProgress(txt, y)\\\\\\\
6984 term.setCursorPos(4, 4)\\\\\\\
6985 print(txt)\\\\\\\
6986 term.setCursorPos(1, y)\\\\\\\
6987 print(\\\\\\\"[ ]\\\\\\\")\\\\\\\
6988 term.setCursorPos(2, y)\\\\\\\
6989 textutils.slowPrint(\\\\\\\"==============================]\\\\\\\", 10)\\\\\\\
6990end\\\\\\\
6991\\\\\\\
6992function drawProgressBig(color)\\\\\\\
6993 term.setCursorPos(4, 10)\\\\\\\
6994 print(\\\\\\\"\\\\\\\\#-------------------------------------------\\\\\\\\#\\\\\\\")\\\\\\\
6995 term.setCursorPos(4, 11)\\\\\\\
6996 print(\\\\\\\"| |\\\\\\\")\\\\\\\
6997 term.setCursorPos(4, 12)\\\\\\\
6998 print(\\\\\\\"\\\\\\\\#-------------------------------------------\\\\\\\\#\\\\\\\")\\\\\\\
6999 term.setBackgroundColor(color or colors.yellow)\\\\\\\
7000 term.setCursorPos(5, 11)\\\\\\\
7001 textutils.slowWrite(\\\\\\\" \\\\\\\", 10)\\\\\\\
7002 term.setBackgroundColor(colors.black)\\\\\\\
7003end\\\\\\\
7004\\\\\\\
7005function printColoredTextLine(y, txt, bg, fg)\\\\\\\
7006 term.setCursorPos(1, y)\\\\\\\
7007 term.setBackgroundColor(bg or colors.lightGray)\\\\\\\
7008 term.write(\\\\\\\" \\\\\\\")\\\\\\\
7009 term.setCursorPos(1, y)\\\\\\\
7010 term.setTextColor(fg or colors.black)\\\\\\\
7011 print(txt)\\\\\\\
7012 term.setBackgroundColor(colors.black)\\\\\\\
7013 term.setTextColor(colors.white)\\\\\\\
7014end\\\\\\\
7015\\\\\\\
7016function outputInfo(header, msg)\\\\\\\
7017 term.setTextColor(colors.cyan)\\\\\\\
7018 write(header..\\\\\\\": \\\\\\\")\\\\\\\
7019 term.setTextColor(colors.lightGray)\\\\\\\
7020 print(msg)\\\\\\\
7021 term.setTextColor(colors.white)\\\\\\\
7022end\\\\\\\
7023\\\\\\\
7024function outputWarning(header, msg)\\\\\\\
7025 term.setTextColor(colors.red)\\\\\\\
7026 write(header..\\\\\\\": \\\\\\\")\\\\\\\
7027 term.setTextColor(colors.orange)\\\\\\\
7028 print(msg)\\\\\\\
7029 term.setTextColor(colors.white)\\\\\\\
7030end\\\\\\\
7031\\\\\\\
7032function outputSuccess(header, msg)\\\\\\\
7033 term.setTextColor(colors.lime)\\\\\\\
7034 write(header..\\\\\\\": \\\\\\\")\\\\\\\
7035 term.setTextColor(colors.green)\\\\\\\
7036 print(msg)\\\\\\\
7037 term.setTextColor(colors.white)\\\\\\\
7038end\\\\\\\
7039\\\\\\\
7040function request(req)\\\\\\\
7041 while true do\\\\\\\
7042 term.setTextColor(colors.cyan)\\\\\\\
7043 write(req .. \\\\\\\"? \\\\\\\")\\\\\\\
7044 term.setTextColor(colors.lightGray)\\\\\\\
7045 write(\\\\\\\"(\\\\\\\")\\\\\\\
7046 term.setTextColor(colors.lime)\\\\\\\
7047 write(\\\\\\\"Y\\\\\\\")\\\\\\\
7048 term.setTextColor(colors.lightGray)\\\\\\\
7049 write(\\\\\\\"/\\\\\\\")\\\\\\\
7050 term.setTextColor(colors.red)\\\\\\\
7051 write(\\\\\\\"N\\\\\\\")\\\\\\\
7052 term.setTextColor(colors.lightGray)\\\\\\\
7053 write(\\\\\\\") \\\\\\\")\\\\\\\
7054 local presel=read()\\\\\\\
7055 if presel==\\\\\\\"Y\\\\\\\" or presel==\\\\\\\"y\\\\\\\" then\\\\\\\
7056 return true\\\\\\\
7057 elseif presel==\\\\\\\"N\\\\\\\" or presel==\\\\\\\"n\\\\\\\" then\\\\\\\
7058 return false\\\\\\\
7059 end\\\\\\\
7060 end\\\\\\\
7061end\\\\\\\
7062\\\\\\\
7063function drawImg(path, x, y)\\\\\\\
7064 if fs.exists(path) and not fs.isDir(path) then\\\\\\\
7065 local img = paintutils.loadImage(path)\\\\\\\
7066 paintutils.drawImage(img, x, y)\\\\\\\
7067 else\\\\\\\
7068 gui.outputWarning(\\\\\\\"gui\\\\\\\", \\\\\\\"image not found\\\\\\\")\\\\\\\
7069 end\\\\\\\
7070end\\\\\\\
7071\\\\\\\
7072function drawDialogBox(prompt)\\\\\\\
7073 drawImg(\\\\\\\"/etc/resources/dialog_box.img\\\\\\\", 1, 1)\\\\\\\
7074 term.setCursorPos(6,7)\\\\\\\
7075 term.setBackgroundColor(colors.white)\\\\\\\
7076 term.setTextColor(colors.black)\\\\\\\
7077 print(prompt)\\\\\\\
7078end\\\\\\\
7079\\\\\\\
7080function drawDialogButton(text, newline)\\\\\\\
7081 stdoutg(text, colors.gray, colors.white)\\\\\\\
7082 if newline then\\\\\\\
7083 stdoutg(\\\\\\\"\\\\\\\\n\\\\\\\", colors.gray, colors.white)\\\\\\\
7084 else\\\\\\\
7085 stdoutg(\\\\\\\" \\\\\\\", colors.gray, colors.white)\\\\\\\
7086 end\\\\\\\
7087end\\\\\\\
7088\\\\\\\
7089function printColored(text, color)\\\\\\\
7090 local tmp = term.getTextColor()\\\\\\\
7091 term.setTextColor(color)\\\\\\\
7092 print(text)\\\\\\\
7093 term.setTextColor(tmp)\\\\\\\
7094end\\\\\\\
7095\\\\\\\
7096function drawBootMenu(array, state1, state2, pos_x, pos_y)\\\\\\\
7097 local select = 1\\\\\\\
7098 local x, y = term.getCursorPos()\\\\\\\
7099 \\\\\\\
7100 while true do\\\\\\\
7101 term.setCursorPos(x, y)\\\\\\\
7102 mprint(array, select, state1, state2, pos_x, pos_y)\\\\\\\
7103 event, key = os.pullEvent(\\\\\\\"key\\\\\\\")\\\\\\\
7104 --Enter\\\\\\\
7105 if key == 28 then \\\\\\\
7106 return select \\\\\\\
7107 end\\\\\\\
7108 \\\\\\\
7109 if #array > 1 then\\\\\\\
7110 --Arrow UP or W key\\\\\\\
7111 if key == 200 or key == 17 then \\\\\\\
7112 \\\\009\\\\009 select = select - 1 \\\\\\\
7113\\\\009\\\\009\\\\009\\\\\\\
7114 if select < 1 then \\\\\\\
7115 select = #array \\\\\\\
7116 end\\\\\\\
7117 --Arrow Down or S key\\\\\\\
7118 elseif key == 208 or key == 31 then \\\\\\\
7119 \\\\009\\\\009 select = select + 1 \\\\\\\
7120 \\\\009\\\\009\\\\009 if select > #array then select = 1 end\\\\\\\
7121 \\\\009 end\\\\\\\
7122 end \\\\\\\
7123 end\\\\\\\
7124end\\\\\\\
7125\\\\\\\
7126function drawContextMenu(...)\\\\\\\
7127 if #arg < 3 or type(arg[3]) ~= \\\\\\\"table\\\\\\\" then error(\\\\\\\"Usage: UI.drawContextMenu(number x, number y, table Element1, table Element2, table Element3...) \\\\\\\\nReturns: string Action \\\\\\\\n<Element> structure: {string Name[, boolean isElementHidden][,number colorOfText]}\\\\\\\") end\\\\\\\
7128 local xSize, ySize = term.getSize()\\\\\\\
7129 \\\\\\\
7130 local function text(x,y,text1,color)\\\\\\\
7131 term.setTextColor(color)\\\\\\\
7132 term.setCursorPos(x,y)\\\\\\\
7133 term.write(text1)\\\\\\\
7134 end\\\\\\\
7135 \\\\\\\
7136 local Objects = {}\\\\\\\
7137 local function newObj(name,isHidden,xStart,xEnd,y)\\\\\\\
7138 Objects[name]={}\\\\\\\
7139 Objects[name][\\\\\\\"isHidden\\\\\\\"] = isHidden\\\\\\\
7140 Objects[name][\\\\\\\"xStart\\\\\\\"] = xStart\\\\\\\
7141 Objects[name][\\\\\\\"xEnd\\\\\\\"] = xEnd\\\\\\\
7142 Objects[name][\\\\\\\"y\\\\\\\"] = y\\\\\\\
7143 end\\\\\\\
7144 \\\\\\\
7145 local theLongestElement = #arg[3][1]\\\\\\\
7146 for i=3,#arg do\\\\\\\
7147 if arg[i] ~= \\\\\\\"-\\\\\\\" and theLongestElement < #arg[i][1] then\\\\\\\
7148 theLongestElement = #arg[i][1]\\\\\\\
7149 end\\\\\\\
7150 end\\\\\\\
7151 \\\\\\\
7152 local xSizeOfMenu = theLongestElement + 4\\\\\\\
7153 local ySizeOfMenu = #arg-2\\\\\\\
7154 \\\\\\\
7155 local xStartToDisplay = nil\\\\\\\
7156 local yStartToDisplay = nil\\\\\\\
7157 \\\\\\\
7158 local function square(x1,y1,width,height,color)\\\\\\\
7159 local string = string.rep(\\\\\\\" \\\\\\\",width)\\\\\\\
7160 term.setBackgroundColor(color)\\\\\\\
7161 for y=y1,(y1+height-1) do\\\\\\\
7162 term.setCursorPos(x1,y)\\\\\\\
7163 term.write(string)\\\\\\\
7164 end\\\\\\\
7165 end\\\\\\\
7166 \\\\\\\
7167 local function drawSeparator(x,y,size)\\\\\\\
7168 term.setTextColor(colors.lightGray)\\\\\\\
7169 term.setCursorPos(x,y)\\\\\\\
7170 term.write(string.rep(\\\\\\\"-\\\\\\\",size))\\\\\\\
7171 end\\\\\\\
7172 \\\\\\\
7173 local function drawMenu(xMenu,yMenu)\\\\\\\
7174 if yMenu+ySizeOfMenu - 1 >= ySize then yMenu = yMenu - (yMenu+ySizeOfMenu - 1 - ySize) - 1 end\\\\\\\
7175 if xMenu+xSizeOfMenu - 1 >= xSize then xMenu = xMenu - (xMenu+xSizeOfMenu - 1 - xSize) - 1 end\\\\\\\
7176 xStartToDisplay = xMenu + 2\\\\\\\
7177 yStartToDisplay = yMenu\\\\\\\
7178 square(xMenu+1,yMenu+1,xSizeOfMenu,ySizeOfMenu,colors.gray)\\\\\\\
7179 square(xMenu,yMenu,xSizeOfMenu,ySizeOfMenu,colors.white)\\\\\\\
7180 for i=3,#arg do\\\\\\\
7181 if arg[i] ~= \\\\\\\"-\\\\\\\" then\\\\\\\
7182 local contextColor = colors.black\\\\\\\
7183 if arg[i][2] == nil and arg[i][3] == nil then\\\\\\\
7184 contextColor = colors.black\\\\\\\
7185 elseif arg[i][2] == false and arg[i][3] == nil then\\\\\\\
7186 contextColor = colors.black\\\\\\\
7187 elseif arg[i][2] == false and arg[i][3] ~= nil then\\\\\\\
7188 contextColor = arg[i][3]\\\\\\\
7189 elseif arg[i][2] == true then\\\\\\\
7190 contextColor = colors.lightGray\\\\\\\
7191 end\\\\\\\
7192 text(xStartToDisplay,yStartToDisplay+i-3,arg[i][1],contextColor)\\\\\\\
7193 newObj(arg[i][1],arg[i][2],xMenu,xMenu+xSizeOfMenu-1,yStartToDisplay+i-3)\\\\\\\
7194 else\\\\\\\
7195 drawSeparator(xMenu,yStartToDisplay+i-3,xSizeOfMenu)\\\\\\\
7196 end\\\\\\\
7197 end\\\\\\\
7198 end\\\\\\\
7199 drawMenu(arg[1],arg[2])\\\\\\\
7200 local event,side,xClick,yClick = os.pullEvent()\\\\\\\
7201 if event == \\\\\\\"monitor_touch\\\\\\\" then side = 1 end\\\\\\\
7202 if event == \\\\\\\"mouse_click\\\\\\\" or event == \\\\\\\"monitor_touch\\\\\\\" then\\\\\\\
7203 for key,val in pairs(Objects) do\\\\\\\
7204 if xClick >= Objects[key][\\\\\\\"xStart\\\\\\\"] and xClick <= Objects[key][\\\\\\\"xEnd\\\\\\\"] and yClick == Objects[key][\\\\\\\"y\\\\\\\"] and Objects[key][\\\\\\\"isHidden\\\\\\\"] == false or xClick >= Objects[key][\\\\\\\"xStart\\\\\\\"] and xClick <= Objects[key][\\\\\\\"xEnd\\\\\\\"] and yClick == Objects[key][\\\\\\\"y\\\\\\\"] and Objects[key][\\\\\\\"isHidden\\\\\\\"] == nil then\\\\\\\
7205 for i=Objects[key][\\\\\\\"xStart\\\\\\\"],Objects[key][\\\\\\\"xEnd\\\\\\\"] do\\\\\\\
7206 paintutils.drawPixel(i,Objects[key][\\\\\\\"y\\\\\\\"],colors.blue)\\\\\\\
7207 end\\\\\\\
7208 text(xStartToDisplay,Objects[key][\\\\\\\"y\\\\\\\"],key,colors.white)\\\\\\\
7209 sleep(0.3)\\\\\\\
7210 return key\\\\\\\
7211 end\\\\\\\
7212 end\\\\\\\
7213 end\\\\\\\
7214end\\\\\\\
7215]]\\\\\\\
7216persist(\\\\\\\"UI\\\\\\\", libcode)\\\\\\\
7217\\\\\\\
7218return 1\\\"\",\
7219}",
7220 "D:lib",
7221 [ 13 ] = "F:startup",
7222 [ 14 ] = "\"if not term.isColor() then\\\
7223 error(\\\"LEFI cannot run on non-advanced computers.\\\")\\\
7224end\\\
7225\\\
7226-- Declare extended Lua attributes\\\
7227\\\
7228rawset(_G, \\\"__declare\\\", function(g, v)\\\
7229 return rawset(_G, g, v)\\\
7230end)\\\
7231\\\
7232__declare(\\\"__declare_api\\\", function(a, g, v)\\\
7233 return rawset(_G[a], g, v)\\\
7234end)\\\
7235\\\
7236__declare(\\\"__try\\\", function(f, e)\\\
7237local r = {pcall(f)}\\\
7238if table.remove(r, 1) == true then\\\
7239 return unpack(r)\\\
7240else\\\
7241 if e ~= nil then\\\
7242 e(unpack(r))\\\
7243 else\\\
7244 return __kstop(0x0000FFFF, unpack(r))\\\
7245 end\\\
7246end\\\
7247end)\\\
7248\\\
7249__declare(\\\"__kstruct\\\", function(t)\\\
7250 if t == _G then\\\
7251 return setmetatable({}, {\\\
7252 __index = t,\\\
7253 __newindex = function(table, key, value)\\\
7254 __kstop(0x00000004, table, key, value)\\\
7255 end,\\\
7256 __metatable = {}\\\
7257 })\\\
7258 else\\\
7259 return setmetatable({}, {\\\
7260 __index = t,\\\
7261 __newindex = function(table, key, value)\\\
7262 __kstop(0x00000005, table, key, value)\\\
7263 end,\\\
7264 __metatable = {}\\\
7265 })\\\
7266 end\\\
7267end)\\\
7268\\\
7269-- declare library persistence loader\\\
7270__declare(\\\"persist\\\", function(n, c)\\\
7271 local h = fs.open(\\\"/tmp/\\\"..n, \\\"w\\\")\\\
7272 h.writeLine(c)\\\
7273 h.close()\\\
7274 os.loadAPI(\\\"/tmp/\\\"..n)\\\
7275 fs.delete(\\\"/tmp/\\\"..n)\\\
7276end)\\\
7277\\\
7278__declare(\\\"drawBootManager\\\", function(opt)\\\
7279 term.setBackgroundColor(colors.black)\\\
7280 term.clear()\\\
7281 term.setCursorPos(1,1)\\\
7282\\009if not opt then\\\
7283 boot_printColoredTextLine(2, \\\" Orbital Boot Manager v1.0 \\\", colors.lightGray, colors.black)\\\
7284 boot_printColoredTextLine(18, \\\" F2=ESI Setup F10=Boot Menu \\\", colors.lightGray, colors.black)\\\
7285\\009else\\\
7286 boot_printColoredTextLine(2, \\\" Orbital Boot Manager v2.1 \\\", colors.red, colors.black)\\\
7287 boot_printColoredTextLine(18, \\\" CTRL+R=Reboot \\\", colors.red, colors.black)\\\
7288\\009end\\\
7289end)\\\
7290\\\
7291local sr = shell.run\\\
7292\\\
7293if not fs.isDir(\\\"/boot\\\") or not loadfile(\\\"/boot/esi/esiboot.b\\\") then\\\
7294 drawBootManager(true)\\\
7295 term.setBackgroundColor(colors.black)\\\
7296 term.setTextColor(colors.red)\\009\\\
7297\\009term.setCursorPos(2,4)\\\
7298\\009print(\\\"The Orbital Boot Manager was unable to boot the\\\")\\\
7299\\009term.setCursorPos(2,5)\\\
7300\\009print(\\\"operating system.\\\")\\\
7301\\009term.setCursorPos(2,7)\\\
7302\\009print(\\\"Status:\\\")\\\
7303\\009term.setCursorPos(2,8)\\\
7304\\009print(\\\"ESI_BINARIES_INVALID (0x00000002)\\\")\\\
7305\\009term.setCursorPos(2,10)\\\
7306\\009print(\\\"Information:\\\")\\\
7307\\009term.setCursorPos(2,11)\\\
7308\\009print(\\\"One or more ESI files are missing.\\\")\\\
7309\\009term.setCursorPos(2,12)\\\
7310\\009print(\\\"Please re-install the operating system.\\\")\\\
7311 while true do\\\
7312\\009 sleep(1)\\\
7313\\009end\\\
7314end\\\
7315\\\
7316sr(\\\"/boot/esi/esiboot.b\\\")\"",
7317 [ 15 ] = "F:startup",
7318}