+ Initial source checkin

This commit is contained in:
NuSkooler 2014-10-16 20:21:06 -06:00
parent 9804c93f2e
commit 9a7e90b9b2
31 changed files with 4361 additions and 0 deletions

285
core/ansi_escape_parser.js Normal file
View File

@ -0,0 +1,285 @@
/* jslint node: true */
'use strict';
var events = require('events');
var util = require('util');
var miscUtil = require('./misc_util.js');
exports.ANSIEscapeParser = ANSIEscapeParser;
function ANSIEscapeParser(options) {
var self = this;
events.EventEmitter.call(this);
this.column = 1;
this.row = 1;
this.flags = 0x00;
this.scrollBack = 0;
options = miscUtil.valueWithDefault(options, {
mciReplaceChar : '',
termHeight : 25,
termWidth : 80,
});
this.mciReplaceChar = miscUtil.valueWithDefault(options.mciReplaceChar, '');
this.termHeight = miscUtil.valueWithDefault(options.termHeight, 25);
this.termWidth = miscUtil.valueWithDefault(options.termWidth, 80);
function getArgArray(array) {
var i = array.length;
while(i--) {
array[i] = parseInt(array[i], 10);
}
return array;
}
self.moveCursor = function(cols, rows) {
self.column += cols;
self.row += rows;
self.column = Math.max(self.column, 1);
self.column = Math.min(self.column, self.termWidth);
self.row = Math.max(self.row, 1);
self.row = Math.min(self.row, self.termHeight);
self.emit('move cursor', self.column, self.row);
self.rowUpdated();
};
self.saveCursorPosition = function() {
self.savedPosition = {
row : self.row,
column : self.column
};
};
self.restoreCursorPosition = function() {
self.row = self.savedPosition.row;
self.column = self.savedPosition.column;
delete self.savedPosition;
self.rowUpdated();
};
self.clearScreen = function() {
// :TODO: should be doing something with row/column?
self.emit('clear screen');
};
self.resetColor = function() {
self.fgColor = 7;
self.bgColor = 0;
};
self.rowUpdated = function() {
self.emit('row update', self.row + self.scrollBack);
};
function literal(text) {
var CR = 0x0d;
var LF = 0x0a;
var charCode;
var len = text.length;
for(var i = 0; i < len; i++) {
charCode = text.charCodeAt(i) & 0xff; // ensure 8 bit
switch(charCode) {
case CR :
self.column = 1;
break;
case LF :
self.row++;
self.rowUpdated();
break;
default :
// wrap
if(self.column === self.termWidth) {
self.column = 1;
self.row++;
self.rowUpdated();
} else {
self.column++;
}
break;
}
if(self.row === 26) {
self.scrollBack++;
self.row--;
self.rowUpdated();
}
}
self.emit('chunk', text);
}
function mci(mciCode, args) {
console.log(mciCode, args);
}
function getProcessedMCI(mci) {
if(self.mciReplaceChar.length > 0) {
return new Array(mci.length + 1).join(self.mciReplaceChar);
} else {
return mci;
}
}
function parseMCI(buffer) {
var mciRe = /\%([A-Z]{2}[0-9]{1,2})(?:\(([0-9A-Z,]+)\))*/g;
var pos = 0;
var match;
var mciCode;
var args;
do {
pos = mciRe.lastIndex;
match = mciRe.exec(buffer);
if(null !== match) {
if(match.index > pos) {
literal(buffer.slice(pos, match.index));
}
mciCode = match[1];
if(match[2]) {
args = match[2].split(',');
} else {
args = [];
}
self.emit('mci', mciCode, args);
self.emit('chunk', getProcessedMCI(match[0]));
}
} while(0 !== mciRe.lastIndex);
if(pos < buffer.length) {
literal(buffer.slice(pos));
}
}
self.parse = function(buffer, savedRe) {
// :TODO: ensure this conforms to ANSI-BBS / CTerm / bansi.txt for movement/etc.
var re = /(?:\x1b\x5b)([\?=;0-9]*?)([ABCDHJKfhlmnpsu])/g;
var pos = 0;
var match;
var opCode;
var args;
// ignore anything past EOF marker, if any
buffer = buffer.split(String.fromCharCode(0x1a), 1)[0];
do {
pos = re.lastIndex;
match = re.exec(buffer);
if(null !== match) {
if(match.index > pos) {
parseMCI(buffer.slice(pos, match.index));
}
opCode = match[2];
args = getArgArray(match[1].split(';'));
escape(opCode, args);
self.emit('chunk', match[0]);
}
} while(0 !== re.lastIndex);
if(pos < buffer.length) {
parseMCI(buffer.slice(pos));
}
self.emit('complete');
};
function escape(opCode, args) {
var arg;
var i;
var len;
switch(opCode) {
// cursor up
case 'A' :
arg = args[0] || 1;
self.moveCursor(0, -arg);
break;
// cursor down
case 'B' :
arg = args[0] || 1;
self.moveCursor(0, arg);
break;
// cursor forward/right
case 'C' :
arg = args[0] || 1;
self.moveCursor(arg, 0);
break;
// cursor back/left
case 'D' :
arg = args[0] || 1;
self.moveCursor(-arg, 0);
break;
case 'f' : // horiz & vertical
case 'H' : // cursor position
self.row = args[0] || 1;
self.column = args[1] || 1;
self.rowUpdated();
break;
// save position
case 's' :
self.saveCursorPosition();
break;
// restore position
case 'u' :
self.restoreCursorPosition();
break;
// set graphic rendition
case 'm' :
for(i = 0, len = args.length; i < len; ++i) {
arg = args[i];
if(0x00 === arg) {
self.flags = 0x00;
self.resetColor();
} else {
switch(Math.floor(arg / 10)) {
case 0 : self.flags |= arg; break;
case 3 : self.fgColor = arg; break;
case 4 : self.bgColor = arg; break;
//case 3 : self.fgColor = arg - 30; break;
//case 4 : self.bgColor = arg - 40; break;
}
}
}
break;
// erase display/screen
case 'J' :
// :TODO: Handle others
if(2 === args[0]) {
self.clearScreen();
}
break;
}
}
}
util.inherits(ANSIEscapeParser, events.EventEmitter);

338
core/ansi_term.js Normal file
View File

@ -0,0 +1,338 @@
/* jslint node: true */
'use strict';
//
// ANSI Terminal Support
//
// Resources:
// * http://ansi-bbs.org/
// * http://www.bbsdocumentary.com/library/PROGRAMS/GRAPHICS/ANSI/ansisys.txt
// * http://en.wikipedia.org/wiki/ANSI_escape_code
//
var assert = require('assert');
var binary = require('binary');
var miscUtil = require('./misc_util.js');
exports.sgr = sgr;
exports.clearScreen = clearScreen;
exports.clearScreenGoHome = clearScreenGoHome;
exports.normal = normal;
exports.goHome = goHome;
exports.disableVT100LineWrapping = disableVT100LineWrapping;
exports.setSyncTermFont = setSyncTermFont;
exports.fromPipeCode = fromPipeCode;
exports.forEachControlCode = forEachControlCode;
//
// See also
// https://github.com/TooTallNate/ansi.js/blob/master/lib/ansi.js
var ESC_CSI = '\u001b[';
var CONTROL = {
up : 'A',
down : 'B',
forward : 'C',
back : 'D',
nextLine : 'E',
prevLine : 'F',
horizAbsolute : 'G',
eraseData : 'J',
scrollUp : 'S',
scrollDown : 'T',
savePos : 's',
restorePos : 'u',
queryPos : '6n',
goto : 'H', // row Pr, column Pc -- same as f
gotoAlt : 'f' // same as H
};
/*
DECTERM stuff. Probably never need
hide : '?25l',
show : '?25h',*/
//
// Select Graphics Rendition
// See http://cvs.synchro.net/cgi-bin/viewcvs.cgi/*checkout*/src/conio/cterm.txt
//
var SGR = {
reset : 0,
bold : 1,
dim : 2,
blink : 5,
fastBlink : 6,
negative : 7,
hidden : 8,
normal : 22,
steady : 25,
positive : 27,
black : 30,
red : 31,
green : 32,
yellow : 33,
blue : 34,
magenta : 35,
cyan : 36,
white : 37,
blackBG : 40,
redBG : 41,
greenBG : 42,
yellowBG : 43,
blueBG : 44,
magentaBG : 45,
cyanBG : 47,
whiteBG : 47,
};
// See http://cvs.synchro.net/cgi-bin/viewcvs.cgi/*checkout*/src/conio/cterm.txt
// :TODO: document
var SYNC_TERM_FONTS = [
'cp437',
'cp1251',
'koi8_r',
'iso8859_2',
'iso8859_4',
'cp866',
'iso8859_9',
'haik8',
'iso8859_8',
'koi8_u',
'iso8859_15',
'iso8859_4',
'koi8_r_b',
'iso8859_4',
'iso8859_5',
'ARMSCII_8',
'iso8859_15',
'cp850',
'cp850',
'cp885',
'cp1251',
'iso8859_7',
'koi8-r_c',
'iso8859_4',
'iso8859_1',
'cp866',
'cp437',
'cp866',
'cp885',
'cp866_u',
'iso8859_1',
'cp1131',
'c64_upper',
'c64_lower',
'c128_upper',
'c128_lower',
'atari',
'pot_noodle',
'mo_soul',
'microknight',
'topaz'
];
// Create methods such as up(), nextLine(),...
Object.keys(CONTROL).forEach(function onControlName(name) {
var code = CONTROL[name];
exports[name] = function() {
var c = code;
if(arguments.length > 0) {
// arguments are array like -- we want an array
c = Array.prototype.slice.call(arguments).map(Math.round).join(';') + code;
}
return ESC_CSI + c;
};
});
// Create a reverse map of CONTROL values to their key/names
/*
var CONTROL_REVERSE_MAP = {};
Object.keys(CONTROL).forEach(function onControlName(name) {
var code = CONTROL[name];
CONTROL_REVERSE_MAP[code] = name;
});
*/
var CONTROL_RESPONSE = {
'R' : 'position',
};
// :TODO: move this to misc utils or such -- use here & parser
function getIntArgArray(array) {
var i = array.length;
while(i--) {
array[i] = parseInt(array[i], 10);
}
return array;
}
// :TODO: rename this
function forEachControlCode(data, cb) {
//var re = /\u001b\[([0-9\;])*[R]/g;
var len = data.length;
var pos = 0;
while(pos < len) {
if(0x1b !== data[pos++] || 0x5b !== data[pos++]) {
continue;
}
var params = '';
while(pos < len) {
var c = data[pos++];
if(((c > 64) && (c < 91)) || ((c > 96) && (c < 123))) {
c = String.fromCharCode(c);
var name = CONTROL_RESPONSE[c];
if(name) {
params = getIntArgArray(params.split(';'));
cb(name, params);
}
}
params += String.fromCharCode(c);
}
}
}
// Create various color methods such as white(), yellowBG(), reset(), ...
Object.keys(SGR).forEach(function onSgrName(name) {
var code = SGR[name];
exports[name] = function() {
return ESC_CSI + code + 'm';
};
});
function sgr() {
//
// - Allow an single array or variable number of arguments
// - Each element can be either a integer or string found in SGR
// which in turn maps to a integer
//
if(arguments.length <= 0) {
return '';
}
var result = '';
// :TODO: this method needs a lot of cleanup!
var args = Array.isArray(arguments[0]) ? arguments[0] : arguments;
for(var i = 0; i < args.length; i++) {
if(typeof args[i] === 'string') {
if(args[i] in SGR) {
if(result.length > 0) {
result += ';';
}
result += SGR[args[i]];
}
} else if(typeof args[i] === 'number') {
if(result.length > 0) {
result += ';';
}
result += args[i];
}
}
return ESC_CSI + result + 'm';
}
///////////////////////////////////////////////////////////////////////////////
// Shortcuts for common functions
///////////////////////////////////////////////////////////////////////////////
function clearScreen() {
return exports.eraseData(2);
}
function clearScreenGoHome() {
return exports.goto(1,1) + exports.eraseData(2);
}
function normal() {
return sgr(['normal', 'reset']);
}
function goHome() {
return exports.goto(); // no params = home = 1,1
}
//
// See http://www.termsys.demon.co.uk/vtANSI_BBS.htm
//
function disableVT100LineWrapping() {
return ESC_CSI + '7l';
}
function setSyncTermFont(name, fontPage) {
fontPage = miscUtil.valueWithDefault(fontPage, 0);
assert(fontPage === 0 || fontPage === 1); // see spec
var i = SYNC_TERM_FONTS.indexOf(name);
if(-1 != i) {
return ESC_CSI + fontPage + ';' + i + ' D';
}
return '';
}
// Also add:
// * fromRenegade(): |<0-23>
// * fromCelerity(): |<case sensitive letter>
// * fromPCBoard(): (@X<bg><fg>@)
// * fromWildcat(): (@<bg><fg>@ (same as PCBoard without 'X' prefix)
// * fromWWIV(): <ctrl-c><0-7>
// * fromSyncronet(): <ctrl-a><colorCode>
// See http://wiki.synchro.net/custom:colors
function fromPipeCode(s) {
if(-1 == s.indexOf('|')) {
return s; // no pipe codes present
}
var result = '';
var re = /\|(\d{2,3}|\|)/g;
var m;
var lastIndex = 0;
while((m = re.exec(s))) {
var val = m[1];
if('|' == val) {
result += '|';
continue;
}
// convert to number
val = parseInt(val, 10);
if(isNaN(val)) {
val = 0;
}
assert(val >= 0 && val <= 256);
var attr = '';
if(7 == val) {
attr = sgr('normal');
} else if (val < 7 || val >= 16) {
attr = sgr(['normal', val]);
} else if (val <= 15) {
attr = sgr(['normal', val - 8, 'bold']);
}
result += s.substr(lastIndex, m.index - lastIndex) + attr;
lastIndex = re.lastIndex;
}
result = (0 === result.length ? s : result + s.substr(lastIndex));
return result;
}

672
core/art.js Normal file
View File

@ -0,0 +1,672 @@
/* jslint node: true */
'use strict';
var fs = require('fs');
var paths = require('path');
var assert = require('assert');
var iconv = require('iconv-lite');
var conf = require('./config.js');
var miscUtil = require('./misc_util.js');
var binary = require('binary');
var events = require('events');
var util = require('util');
var ansi = require('./ansi_term.js');
var aep = require('./ansi_escape_parser.js');
exports.getArt = getArt;
exports.getArtFromPath = getArtFromPath;
exports.display = display;
exports.defaultEncodingFromExtension = defaultEncodingFromExtension;
exports.ArtDisplayer = ArtDisplayer;
var SAUCE_SIZE = 128;
var SAUCE_ID = new Buffer([0x53, 0x41, 0x55, 0x43, 0x45]); // 'SAUCE'
var COMNT_ID = new Buffer([0x43, 0x4f, 0x4d, 0x4e, 0x54]); // 'COMNT'
// :TODO: Return MCI code information
// :TODO: process SAUCE comments
// :TODO: return font + font mapped information from SAUCE
var SUPPORTED_ART_TYPES = {
// :TODO: the defualt encoding are really useless if they are all the same ...
// perhaps .ansamiga and .ascamiga could be supported as well as overrides via conf
'.ans' : { name : 'ANSI', defaultEncoding : 'cp437', eof : 0x1a },
'.asc' : { name : 'ASCII', defaultEncoding : 'cp437', eof : 0x1a },
'.pcb' : { name : 'PCBoard', defaultEncoding : 'cp437', eof : 0x1a },
'.bbs' : { name : 'Wildcat', defaultEncoding : 'cp437', eof : 0x1a },
'.txt' : { name : 'Text', defaultEncoding : 'cp437', eof : 0x1a }, // :TODO: think about this more...
// :TODO: extentions for wwiv, renegade, celerity, syncronet, ...
// :TODO: extension for atari
// :TODO: extension for topaz ansi/ascii.
};
//
// See
// http://www.acid.org/info/sauce/sauce.htm
//
// :TODO: Move all SAUCE stuff to sauce.js
function readSAUCE(data, cb) {
if(data.length < SAUCE_SIZE) {
cb(new Error('No SAUCE record present'));
return;
}
var offset = data.length - SAUCE_SIZE;
var sauceRec = data.slice(offset);
binary.parse(sauceRec)
.buffer('id', 5)
.buffer('version', 2)
.buffer('title', 35)
.buffer('author', 20)
.buffer('group', 20)
.buffer('date', 8)
.word32lu('fileSize')
.word8('dataType')
.word8('fileType')
.word16lu('tinfo1')
.word16lu('tinfo2')
.word16lu('tinfo3')
.word16lu('tinfo4')
.word8('numComments')
.word8('flags')
.buffer('tinfos', 22) // SAUCE 00.5
.tap(function onVars(vars) {
if(!SAUCE_ID.equals(vars.id)) {
cb(new Error('No SAUCE record present'));
return;
}
var ver = vars.version.toString('cp437');
if('00' !== ver) {
cb(new Error('Unsupported SAUCE version: ' + ver));
return;
}
var sauce = {
id : vars.id.toString('cp437'),
version : vars.version.toString('cp437'),
title : vars.title.toString('cp437').trim(),
author : vars.author.toString('cp437').trim(),
group : vars.group.toString('cp437').trim(),
date : vars.date.toString('cp437').trim(),
fileSize : vars.fileSize,
dataType : vars.dataType,
fileType : vars.fileType,
tinfo1 : vars.tinfo1,
tinfo2 : vars.tinfo2,
tinfo3 : vars.tinfo3,
tinfo4 : vars.tinfo4,
numComments : vars.numComments,
flags : vars.flags,
tinfos : vars.tinfos,
};
var dt = SAUCE_DATA_TYPES[sauce.dataType];
if(dt && dt.parser) {
sauce[dt.name] = dt.parser(sauce);
}
cb(null, sauce);
});
}
// :TODO: These need completed:
var SAUCE_DATA_TYPES = {};
SAUCE_DATA_TYPES[0] = { name : 'None' };
SAUCE_DATA_TYPES[1] = { name : 'Character', parser : parseCharacterSAUCE };
SAUCE_DATA_TYPES[2] = 'Bitmap';
SAUCE_DATA_TYPES[3] = 'Vector';
SAUCE_DATA_TYPES[4] = 'Audio';
SAUCE_DATA_TYPES[5] = 'BinaryText';
SAUCE_DATA_TYPES[6] = 'XBin';
SAUCE_DATA_TYPES[7] = 'Archive';
SAUCE_DATA_TYPES[8] = 'Executable';
var SAUCE_CHARACTER_FILE_TYPES = {};
SAUCE_CHARACTER_FILE_TYPES[0] = 'ASCII';
SAUCE_CHARACTER_FILE_TYPES[1] = 'ANSi';
SAUCE_CHARACTER_FILE_TYPES[2] = 'ANSiMation';
SAUCE_CHARACTER_FILE_TYPES[3] = 'RIP script';
SAUCE_CHARACTER_FILE_TYPES[4] = 'PCBoard';
SAUCE_CHARACTER_FILE_TYPES[5] = 'Avatar';
SAUCE_CHARACTER_FILE_TYPES[6] = 'HTML';
SAUCE_CHARACTER_FILE_TYPES[7] = 'Source';
SAUCE_CHARACTER_FILE_TYPES[8] = 'TundraDraw';
//
// Map of SAUCE font -> encoding hint
//
// Note that this is the same mapping that x84 uses. Be compatible!
//
var SAUCE_FONT_TO_ENCODING_HINT = {
'Amiga MicroKnight' : 'amiga',
'Amiga MicroKnight+' : 'amiga',
'Amiga mOsOul' : 'amiga',
'Amiga P0T-NOoDLE' : 'amiga',
'Amiga Topaz 1' : 'amiga',
'Amiga Topaz 1+' : 'amiga',
'Amiga Topaz 2' : 'amiga',
'Amiga Topaz 2+' : 'amiga',
'Atari ATASCII' : 'atari',
'IBM EGA43' : 'cp437',
'IBM EGA' : 'cp437',
'IBM VGA25G' : 'cp437',
'IBM VGA50' : 'cp437',
'IBM VGA' : 'cp437',
};
['437', '720', '737', '775', '819', '850', '852', '855', '857', '858',
'860', '861', '862', '863', '864', '865', '866', '869', '872'].forEach(function onPage(page) {
var codec = 'cp' + page;
SAUCE_FONT_TO_ENCODING_HINT['IBM EGA43 ' + page] = codec;
SAUCE_FONT_TO_ENCODING_HINT['IBM EGA ' + page] = codec;
SAUCE_FONT_TO_ENCODING_HINT['IBM VGA25g ' + page] = codec;
SAUCE_FONT_TO_ENCODING_HINT['IBM VGA50 ' + page] = codec;
SAUCE_FONT_TO_ENCODING_HINT['IBM VGA ' + page] = codec;
});
function parseCharacterSAUCE(sauce) {
var result = {};
result.fileType = SAUCE_CHARACTER_FILE_TYPES[sauce.fileType] || 'Unknown';
if(sauce.fileType === 0 || sauce.fileType === 1 || sauce.fileType === 2) {
var i = 0;
while(i < sauce.tinfos.length && sauce.tinfos[i] !== 0x00) {
++i;
}
var fontName = sauce.tinfos.slice(0, i).toString('cp437');
if(fontName.length > 0) {
result.fontName = fontName;
}
}
return result;
}
function sliceAtEOF(data, eofMarker) {
var eof = data.length;
// :TODO: max scan back or other beter way of doing this?!
for(var i = data.length - 1; i > 0; i--) {
if(data[i] === eofMarker) {
eof = i;
break;
}
}
return data.slice(0, eof);
}
function getArtFromPath(path, options, cb) {
fs.readFile(path, function onData(err, data) {
if(err) {
cb(err);
return;
}
//
// Convert from encodedAs -> j
//
var ext = paths.extname(path).toLowerCase();
var encoding = options.encodedAs || defaultEncodingFromExtension(ext);
// :TODO: how are BOM's currently handled if present? Are they removed? Do we need to?
function sliceOfData() {
if(options.fullFile === true) {
return iconv.decode(data, encoding);
} else {
var eofMarker = defaultEofFromExtension(ext);
return iconv.decode(sliceAtEOF(data, eofMarker), encoding);
}
}
function getResult(sauce) {
var result = {
data : sliceOfData(),
fromPath : path,
};
if(sauce) {
result.sauce = sauce;
}
return result;
}
if(options.readSauce === true) {
readSAUCE(data, function onSauce(err, sauce) {
if(err) {
cb(null, getResult());
} else {
//
// If a encoding was not provided & we have a mapping from
// the information provided by SAUCE, use that.
//
if(!options.encodedAs) {
if(sauce.Character && sauce.Character.fontName) {
var enc = SAUCE_FONT_TO_ENCODING_HINT[sauce.Character.fontName];
if(enc) {
encoding = enc;
}
}
}
cb(null, getResult(sauce));
}
});
} else {
cb(null, getResult());
}
});
}
function getArt(name, options, cb) {
var ext = paths.extname(name);
options.basePath = miscUtil.valueWithDefault(options.basePath, conf.config.paths.art);
options.asAnsi = miscUtil.valueWithDefault(options.asAnsi, true);
// :TODO: make use of asAnsi option and convert from supported -> ansi
if('' !== ext) {
options.types = [ ext.toLowerCase() ];
} else {
if(typeof options.types === 'undefined') {
options.types = Object.keys(SUPPORTED_ART_TYPES);
} else if(typeof options.types === 'string') {
options.types = [ options.types.toLowerCase() ];
}
}
// If an extension is provided, just read the file now
if('' !== ext) {
var directPath = paths.join(options.basePath, name);
getArtFromPath(directPath, options, cb);
return;
}
fs.readdir(options.basePath, function onFiles(err, files) {
if(err) {
cb(err);
return;
}
var filtered = files.filter(function onFile(file) {
//
// Ignore anything not allowed in |options.types|
//
var fext = paths.extname(file);
if(options.types.indexOf(fext.toLowerCase()) < 0) {
return false;
}
var bn = paths.basename(file, fext).toLowerCase();
if(options.random) {
var suppliedBn = paths.basename(name, fext).toLowerCase();
//
// Random selection enabled. We'll allow for
// basename1.ext, basename2.ext, ...
//
if(bn.indexOf(suppliedBn) !== 0) {
return false;
}
var num = bn.substr(suppliedBn.length);
if(num.length > 0) {
if(isNaN(parseInt(num, 10))) {
return false;
}
}
} else {
//
// We've already validated the extension (above). Must be an exact
// match to basename here
//
if(bn != paths.basename(name, fext).toLowerCase()) {
return false;
}
}
return true;
});
if(filtered.length > 0) {
//
// We should now have:
// - Exactly (1) item in |filtered| if non-random
// - 1:n items in |filtered| to choose from if random
//
var readPath;
if(options.random) {
readPath = paths.join(options.basePath, filtered[Math.floor(Math.random() * filtered.length)]);
} else {
assert(1 === filtered.length);
readPath = paths.join(options.basePath, filtered[0]);
}
getArtFromPath(readPath, options, cb);
} else {
cb(new Error('No matching art for supplied criteria'));
}
});
}
// :TODO: need a showArt()
// - center (if term width > 81)
// - interruptable
// - pausable: by user key and/or by page size (e..g term height)
function defaultEncodingFromExtension(ext) {
return SUPPORTED_ART_TYPES[ext.toLowerCase()].defaultEncoding;
}
function defaultEofFromExtension(ext) {
return SUPPORTED_ART_TYPES[ext.toLowerCase()].eof;
}
function ArtDisplayer(client) {
if(!(this instanceof ArtDisplayer)) {
return new ArtDisplayer(client);
}
events.EventEmitter.call(this);
this.client = client;
}
util.inherits(ArtDisplayer, events.EventEmitter);
// :TODO: change to display(art, options, cb)
// cb(err, mci)
function display(art, options, cb) {
if(!art || 0 === art.length) {
cb(new Error('Missing or empty art'));
return;
}
if('undefined' === typeof options) {
cb(new Error('Missing options'));
return;
}
if('undefined' === typeof options.client) {
cb(new Error('Missing client in options'));
return;
}
var cancelKeys = miscUtil.valueWithDefault(options.cancelKeys, []);
var pauseKeys = miscUtil.valueWithDefault(options.pauseKeys, []);
var pauseAtTermHeight = miscUtil.valueWithDefault(options.pauseAtTermHeight, false);
var mciReplaceChar = miscUtil.valueWithDefault(options.mciReplaceChar, '');
// :TODO: support pause/cancel & pause @ termHeight
var canceled = false;
var parser = new aep.ANSIEscapeParser({
mciReplaceChar : mciReplaceChar,
termHeight : options.client.term.termHeight,
termWidth : options.client.term.termWidth,
});
var mci = {};
var mciPosQueue = [];
var emitter = null;
var parseComplete = false;
parser.on('mci', function onMCI(mciCode, args) {
if(mci[mciCode]) {
mci[mciCode].altColor = {
fg : parser.fgColor,
bg : parser.bgColor,
flags : parser.flags,
};
} else {
mci[mciCode] = {
args : args,
color : {
fg : parser.fgColor,
bg : parser.bgColor,
flags : parser.flags,
}
};
mciPosQueue.push(mciCode);
if(!emitter) {
emitter = options.client.on('onPosition', function onPosition(pos) {
if(mciPosQueue.length > 0) {
var forMciCode = mciPosQueue.shift();
mci[forMciCode].position = pos;
if(parseComplete && 0 === mciPosQueue.length) {
cb(null, mci);
}
}
});
}
options.client.term.write(ansi.queryPos());
}
});
parser.on('chunk', function onChunk(chunk) {
options.client.term.write(chunk);
});
parser.on('complete', function onComplete() {
parseComplete = true;
if(0 === mciPosQueue.length) {
cb(null, mci);
}
});
parser.parse(art);
}
ArtDisplayer.prototype.display = function(art, options) {
var client = this.client;
var self = this;
var cancelKeys = miscUtil.valueWithDefault(options.cancelKeys, []);
var pauseKeys = miscUtil.valueWithDefault(options.pauseKeys, []);
var pauseAtTermHeight = miscUtil.valueWithDefault(options.pauseAtTermHeight, false);
var canceled = false;
if(cancelKeys.length > 0 || pauseKeys.length > 0) {
var onDataKeyCheck = function(data) {
var key = String.fromCharCode(data[0]);
if(-1 !== cancelKeys.indexOf(key)) {
canceled = true;
removeDataListener();
}
};
client.on('data', onDataKeyCheck);
}
function removeDataListener() {
client.removeListener('data', onDataKeyCheck);
}
//
// Try to split lines supporting various linebreaks we may encounter:
// - DOS \r\n
// - *nix \n
// - Old Apple \r
// - Unicode PARAGRAPH SEPARATOR (U+2029) and LINE SEPARATOR (U+2028)
//
// See also http://stackoverflow.com/questions/5034781/js-regex-to-split-by-line
//
var lines = art.split(/\r?\n|\r|[\u2028\u2029]/);
var i = 0;
var count = lines.length;
if(0 === count) {
return;
}
var termHeight = client.term.termHeight;
var aep = require('./ansi_escape_parser.js');
var p = new aep.ANSIEscapeParser();
var currentRow = 0;
var lastRow = 0;
p.on('row update', function onRowUpdated(row) {
currentRow = row;
});
//--------
var mci = {};
var mciPosQueue = [];
var parseComplete = false;
var emitter = null;
p.on('mci', function onMCI(mciCode, args) {
if(mci[mciCode]) {
mci[mciCode].fgColorAlt = p.fgColor;
mci[mciCode].bgColorAlt = p.bgColor;
mci[mciCode].flagsAlt = p.flags;
} else {
mci[mciCode] = {
args : args,
fgColor : p.fgColor,
bgColor : p.bgColor,
flags : p.flags,
};
mciPosQueue.push(mciCode);
if(!emitter) {
emitter = client.on('onPosition', function onPosition(pos) {
if(mciPosQueue.length > 0) {
var mc = mciPosQueue.shift();
console.log('position @ ' + mc + ': ' + pos);
mci[mc].pos = pos;
if(parseComplete && 0 === mciPosQueue.length) {
//console.log(mci);
var p1 = mci['LV1'].pos;
client.term.write(ansi.sgr(['red']));
var g = ansi.goto(p1);
console.log(g);
client.term.write(ansi.goto(p1[0], p1[1]));
client.term.write('Hello, World');
}
}
});
}
}
});
p.on('chunk', function onChunk(chunk) {
client.term.write(chunk);
});
p.on('complete', function onComplete() {
//console.log(mci);
parseComplete = true;
if(0 === mciPosQueue.length) {
console.log('mci from complete');
console.log(mci);
}
});
p.parse(art);
//-----------
/*
var line;
(function nextLine() {
if(i === count) {
self.emit('complete');
removeDataListener();
return;
}
if(canceled) {
self.emit('canceled');
removeDataListener();
return;
}
line = lines[i];
client.term.write(line + '\n');
p.parse(line + '\r\n');
i++;
if(pauseAtTermHeight && currentRow !== lastRow && (0 === currentRow % termHeight)) {
lastRow = currentRow;
client.getch(function onKey(k) {
nextLine();
});
} else {
setTimeout(nextLine, 20);
}
})();
*/
/*
(function nextLine() {
if(i === count) {
client.emit('complete', true);
removeDataListener();
return;
}
if(canceled) {
console.log('canceled');
client.emit('canceled');
removeDataListener();
return;
}
client.term.write(lines[i] + '\n');
//
// :TODO: support pauseAtTermHeight:
//
// - All cursor movement should be recorded for pauseAtTermHeight support &
// handling > termWidth scenarios
// - MCI codes should be processed
// - All other ANSI/CSI ignored
// - Count normal chars
//
//setTimeout(nextLine, 20);
//i++;
if(pauseAtTermHeight && i > 0 && (0 === i % termHeight)) {
console.log('pausing @ ' + i);
client.getch(function onKey() {
i++;
nextLine();
});
} else {
i++;
// :TODO: If local, use setTimeout(nextLine, 20) or so -- allow to pause/cancel
//process.nextTick(nextLine);
setTimeout(nextLine, 20);
}
})();
*/
};
//
// ANSI parser for quick scanning & handling
// of basic ANSI sequences that can be used for output to clients:
//
function ANSIOutputParser(ansi) {
//
// cb's
// - onMCI
// - onTermHeight
// -
}

155
core/bbs.js Normal file
View File

@ -0,0 +1,155 @@
/* jslint node: true */
'use strict';
// ENiGMA½
var conf = require('./config.js');
var modules = require('./modules.js');
var logger = require('./logger.js');
var miscUtil = require('./misc_util.js');
var iconv = require('iconv-lite');
var paths = require('path');
exports.bbsMain = function() {
var mainArgs = parseArgs();
var configPathSupplied = false;
var configPath = conf.defaultPath();
if(mainArgs.indexOf('--help') > 0) {
// :TODO: display help
} else {
var argCount = mainArgs.length;
for(var i = 0; i < argCount; ++i) {
var arg = mainArgs[i];
if('--config' == arg) {
configPathSupplied = true;
configPath = mainArgs[i + 1];
}
}
}
try {
conf.initFromFile(configPath);
} catch(e) {
//
// If the user supplied a config and we can't read, parse, whatever
// then output a error and bail.
//
if(configPathSupplied) {
if(e.code === 'ENOENT') {
console.error('Configuration file does not exist: ' + configPath);
}
return;
}
console.log('No configuration file found, creating defaults.');
conf.createDefault();
}
logger.init();
preServingInit();
startListening();
process.on('SIGINT', function onSigInt() {
// :TODO: for any client in |clientConnections|, if 'ready', send a "Server Disconnecting" + semi-gracefull hangup
// e.g. client.disconnectNow()
logger.log.info('Process interrupted, shutting down');
process.exit();
});
};
function parseArgs() {
var args = [];
process.argv.slice(2).forEach(function(val, index, array) {
args.push(val);
});
return args;
}
function preServingInit() {
iconv.extendNodeEncodings();
}
var clientConnections = [];
function startListening() {
if(!conf.config.servers) {
// :TODO: Log error ... output to stderr as well. We can do it all with the logger
return [];
}
modules.loadModulesForCategory('servers', function onServerModule(err, module) {
if(err) {
logger.log.info(err);
return;
}
var port = parseInt(module.runtime.config.port);
if(isNaN(port)) {
logger.log.error({ port : module.runtime.config.port, server : module.moduleInfo.name }, 'Cannot load server (Invalid port)');
return;
}
var server = module.createServer();
// :TODO: handle maxConnections, e.g. conf.maxConnections
server.on('client', function onClient(client) {
//
// Start tracking the client. We'll assign it an ID which is
// just the index in our connections array.
//
if(typeof client.runtime === 'undefined') {
client.runtime = {};
}
addNewClient(client);
//client.runtime.id = clientConnections.push(client) - 1;
//logger.log.info({ clientId : client.runtime.id, from : client.address(), server : module.moduleInfo.name }, 'Client connected');
client.on('ready', function onClientReady() {
// Go to module -- use default error handler
modules.goto(conf.config.entryMod, client);
});
client.on('end', function onClientEnd() {
logger.log.info({ clientId : client.runtime.id }, 'Client disconnected');
removeClient(client);
});
client.on('error', function onClientError(err) {
logger.log.info({ clientId : client.runtime.id }, 'Connection error: %s' % err.message);
});
client.on('close', function onClientClose(hadError) {
var l = hadError ? logger.log.info : logger.log.debug;
l({ clientId : client.runtime.id }, 'Connection closed');
removeClient(client);
});
});
server.listen(port);
logger.log.info({ server : module.moduleInfo.name, port : port }, 'Listening for connections');
});
}
function addNewClient(client) {
var id = client.runtime.id = clientConnections.push(client) - 1;
logger.log.debug('Connection count is now %d', clientConnections.length);
return id;
}
function removeClient(client) {
var i = clientConnections.indexOf(client);
if(i > -1) {
clientConnections.splice(i, 1);
logger.log.debug('Connection count is now %d', clientConnections.length);
}
}

89
core/client.js Normal file
View File

@ -0,0 +1,89 @@
/* jslint node: true */
'use strict';
var stream = require('stream');
var term = require('./client_term.js');
var assert = require('assert');
var miscUtil = require('./misc_util.js');
var ansi = require('./ansi_term.js');
var logger = require('./logger.js');
exports.Client = Client;
function Client(input, output) {
stream.call(this);
var self = this;
this.input = input;
this.output = output;
this.term = new term.ClientTerminal(this.output);
self.on('data', function onData(data) {
console.log('data: ' + data.length);
handleANSIControlResponse(data);
});
function handleANSIControlResponse(data) {
console.log(data);
ansi.forEachControlCode(data, function onControlResponse(name, params) {
var eventName = 'on' + name[0].toUpperCase() + name.substr(1);
console.log(eventName + ': ' + params);
self.emit(eventName, params);
});
}
}
require('util').inherits(Client, stream);
Client.prototype.end = function () {
return this.output.end.apply(this.output, arguments);
};
Client.prototype.destroy = function () {
return this.output.destroy.apply(this.output, arguments);
};
Client.prototype.destroySoon = function () {
return this.output.destroySoon.apply(this.output, arguments);
};
Client.prototype.getch = function(cb) {
this.input.once('data', function onData(data) {
// :TODO: needs work. What about F keys and the like?
assert(data.length === 1);
cb(data);
});
};
Client.prototype.address = function() {
return this.input.address();
};
///////////////////////////////////////////////////////////////////////////////
// Default error handlers
///////////////////////////////////////////////////////////////////////////////
Client.prototype.defaultHandlerMissingMod = function(err) {
var self = this;
function handler(err) {
logger.log.error(err);
self.term.write('An unrecoverable error has been encountered!\n');
self.term.write('This has been logged for your SysOp to review.\n');
self.term.write('\nGoodbye!\n');
//self.term.write(err);
//if(miscUtil.isDevelopment() && err.stack) {
// self.term.write('\n' + err.stack + '\n');
//}
self.end();
}
return handler;
};

101
core/client_term.js Normal file
View File

@ -0,0 +1,101 @@
/* jslint node: true */
'use strict';
// ENiGMA½
var logger = require('./logger.js');
var iconv = require('iconv-lite');
var assert = require('assert');
iconv.extendNodeEncodings();
exports.ClientTerminal = ClientTerminal;
function ClientTerminal(output) {
this.output = output;
var self = this;
var outputEncoding = 'cp437';
assert(iconv.encodingExists(outputEncoding));
// convert line feeds such as \n -> \r\n
this.convertLF = true;
//
// Some terminal we handle specially
// They can also be found in this.env{}
//
var termType = 'unknown';
var termHeight = 0;
var termWidth = 0;
// Raw values set by e.g. telnet NAWS, ENVIRONMENT, etc.
this.env = {};
Object.defineProperty(this, 'outputEncoding', {
get : function() {
return outputEncoding;
},
set : function(enc) {
if(iconv.encodingExists(enc)) {
outputEncoding = enc;
} else {
logger.log.warn({ encoding : enc }, 'Unknown encoding');
}
}
});
Object.defineProperty(this, 'termType', {
get : function() {
return termType;
},
set : function(ttype) {
termType = ttype.toLowerCase();
//
// ANSI terminals should be encoded to CP437
//
if('ansi' == termType) {
this.outputEncoding = 'cp437';
} else {
// :TODO: See how x84 does this -- only set if local/remote are binary
this.outputEncoding = 'utf8';
}
}
});
Object.defineProperty(this, 'termWidth', {
get : function() {
return termWidth;
},
set : function(width) {
if(width > 0) {
termWidth = width;
}
}
});
Object.defineProperty(this, 'termHeight', {
get : function() {
return termHeight;
},
set : function(height) {
if(height > 0) {
termHeight = height;
}
}
});
}
ClientTerminal.prototype.isANSI = function() {
return 'ansi' === this.termType;
};
ClientTerminal.prototype.write = function(s) {
if(this.convertLF && typeof s === 'string') {
s = s.replace(/\n/g, '\r\n');
}
this.output.write(iconv.encode(s, this.outputEncoding));
};

50
core/config.js Normal file
View File

@ -0,0 +1,50 @@
/* jslint node: true */
'use strict';
var fs = require('fs');
var paths = require('path');
var miscUtil = require('./misc_util.js');
module.exports = {
config : undefined,
defaultPath : function() {
var base = miscUtil.resolvePath('~/');
if(base) {
return paths.join(base, '.enigmabbs', 'config.json');
}
},
initFromFile : function(path, cb) {
var data = fs.readFileSync(path, 'utf8');
this.config = JSON.parse(data);
},
createDefault : function() {
this.config = {
bbsName : 'Another Fine ENiGMA½ BBS',
entryMod : 'connect',
paths : {
mods : paths.join(__dirname, './../mods/'),
servers : paths.join(__dirname, './servers/'),
art : paths.join(__dirname, './../mods/art/'),
logs : paths.join(__dirname, './../logs/'), // :TODO: set up based on system, e.g. /var/logs/enigmabbs or such
},
servers : {
telnet : {
port : 8888,
enabled : true,
},
ssh : {
port : 8889,
enabled : false,
rsaPrivateKey : paths.join(__dirname, './../misc/default_key.rsa'),
dsaPrivateKey : paths.join(__dirname, './../misc/default_key.dsa'),
}
},
};
}
};

64
core/line_editor.js Normal file
View File

@ -0,0 +1,64 @@
"use strict";
var assert = require('assert');
var miscUtil = require('./misc_util.js');
exports.LineEditor = LineEditor;
var STANDARD_KEYSET = {
refresh : [ 12 ],
backspace : [ 8, 127 ],
backword : [ 23 ],
enter : [ 10 ],
exit : [ 27 ],
};
// :TODO: Rename to TextEdit
// :TODO: TextEdit should be single or multi line
function LineEditor(client, options) {
var self = this;
self.client = client;
self.valueText = '';
if(typeof options !== 'undefined') {
self.options.keyset = miscUtil.valueWithDefault(options.keyset, STANDARD_KEYSET);
} else {
self.options = {
keyset : STANDARD_KEYSET,
};
}
this.client.on('data', function onData(data) {
assert(1 === data.length);
self.onCh(data);
});
};
LineEditor.prototype.isKey = function(setName, ch) {
return this.options.keyset[setName].indexOf(ch) > -1;
}
LineEditor.prototype.onCh = function(ch) {
if(this.isKey('refresh', ch)) {
} else if(this.isKey('backspace', ch)) {
} else if(this.isKey('backword', ch)) {
} else if(this.isKey('enter', ch)) {
} else if(this.isKey('exit', ch)) {
} else {
// :TODO: filter out chars
// :TODO: check max width
this.valueText += ch;
this.client.term.write(ch);
}
};

39
core/logger.js Normal file
View File

@ -0,0 +1,39 @@
"use strict";
var bunyan = require('bunyan');
var miscUtil = require('./misc_util.js');
var paths = require('path');
var conf = require('./config.js');
module.exports = {
log : undefined,
init : function() {
//var ringBufferLimit = miscUtil.valueWithDefault(config.logRingBufferLimit, 100);
var logPath = miscUtil.valueWithDefault(conf.config.paths.logs);
var logFile = paths.join(logPath, 'enigma-bbs.log');
// :TODO: make this configurable --
// user should be able to configure rotations, levels to file vs ringBuffer,
// completely disable logging, etc.
this.log = bunyan.createLogger({
name : 'ENiGMA½ BBS',
streams : [
{
type : 'rotating-file',
path : logFile,
period : '1d',
count : 3,
level : 'trace'
}
/*,
{
type : 'raw',
stream : ringBuffer,
level : 'trace'
}*/
]
});
}
};

28
core/misc_util.js Normal file
View File

@ -0,0 +1,28 @@
"use strict";
var paths = require('path');
exports.isProduction = isProduction;
exports.isDevelopment = isDevelopment;
exports.valueWithDefault = valueWithDefault;
exports.resolvePath = resolvePath;
function isProduction() {
var env = process.env.NODE_ENV || 'dev';
return 'production' === env;
};
function isDevelopment() {
return (!(isProduction()));
};
function valueWithDefault(val, defVal) {
return (typeof val !== 'undefined' ? val : defVal);
};
function resolvePath(path) {
if(path.substr(0, 2) === '~/') {
path = (process.env.HOME || process.env.HOMEPATH || process.env.HOMEDIR || process.cwd()) + path.substr(1);
}
return paths.resolve(path);
};

85
core/modules.js Normal file
View File

@ -0,0 +1,85 @@
/* jslint node: true */
'use strict';
var fs = require('fs');
var paths = require('path');
var conf = require('./config.js');
var miscUtil = require('./misc_util.js');
var logger = require('./logger.js');
// exports
exports.loadModule = loadModule;
exports.loadModulesForCategory = loadModulesForCategory;
exports.goto = goto;
function loadModule(name, category, cb) {
var config = conf.config;
var path = config.paths[category];
if(!path) {
cb(new Error('not sure where to look for "' + name + '" of category "' + category + '"'));
return;
}
// update conf to point at this module's section, if any
config = config[category] ? config[category][name] : null;
if(config && false === config.enabled) {
cb(new Error('module "' + name + '" is disabled'));
return;
}
try {
var mod = require(paths.join(path, name + '.js'));
if(!mod.moduleInfo) {
cb(new Error('module is missing \'moduleInfo\' section'));
return;
}
mod.runtime = {
config : config
};
cb(null, mod);
} catch(e) {
cb(e);
}
};
function loadModulesForCategory(category, cb) {
var path = conf.config.paths[category];
fs.readdir(path, function onFiles(err, files) {
if(err) {
cb(err);
return;
}
var filtered = files.filter(function onFilter(file) { return '.js' === paths.extname(file); });
filtered.forEach(function onFile(file) {
var modName = paths.basename(file, '.js');
loadModule(paths.basename(file, '.js'), category, cb);
});
});
};
function goto(name, client, cb) {
// Assign a default missing module handler callback if none was provided
cb = miscUtil.valueWithDefault(cb, client.defaultHandlerMissingMod());
loadModule(name, 'mods', function onMod(err, mod) {
if(err) {
cb(err);
} else {
try {
logger.log.debug({ moduleName : name }, 'Goto module');
mod.entryPoint(client);
} catch (e) {
cb(e);
}
}
});
};

30
core/servers/ssh.js Normal file
View File

@ -0,0 +1,30 @@
"use strict";
var libssh = require('ssh');
var conf = require('../config.js');
/*
Notes on getting libssh to work. This will ultimately require some contribs back
* Can't install without --nodedir= as had to upgrade node on the box for other reasons
* From ssh dir, node-gyp --nodedir=... configure build
* nan is out of date and doesn't work with existing node. Had to update. ( was "~0.6.0") (npm update after this)
*
*/
exports.moduleInfo = {
name : 'SSH',
desc : 'SSH Server',
author : 'NuSkooler'
};
function createServer() {
var server = libssh.createServer(
conf.config.servers.ssh.rsaPrivateKey,
conf.config.servers.ssh.dsaPrivateKey);
server.on('connection', function onConnection(session) {
console.log('ermergerd')
});
return server;
}

729
core/servers/telnet.js Normal file
View File

@ -0,0 +1,729 @@
/* jslint node: true */
'use strict';
// ENiGMA½
var baseClient = require('../client.js');
var logger = require('../logger.js');
var net = require('net');
var buffers = require('buffers');
var binary = require('binary');
var stream = require('stream');
var assert = require('assert');
//var debug = require('debug')('telnet');
exports.moduleInfo = {
name : 'Telnet',
desc : 'Telnet Server',
author : 'NuSkooler'
};
exports.createServer = createServer;
//
// Telnet Protocol Resources
// * http://pcmicro.com/netfoss/telnet.html
// * http://mud-dev.wikidot.com/telnet:negotiation
//
/*
TODO:
* Document COMMANDS -- add any missing
* Document OPTIONS -- add any missing
* Internally handle OPTIONS:
* Some should be emitted generically
* Some shoudl be handled internally -- denied, handled, etc.
*
* Allow term (ttype) to be set by environ sub negotiation
* Process terms in loop.... research needed
* Handle will/won't
* Handle do's, ..
* Some won't should close connection
* Options/Commands we don't understand shouldn't crash the server!!
*/
var COMMANDS = {
SE : 240, // End of Sub-Negotation Parameters
NOP : 241, // No Operation
DM : 242, // Data Mark
BRK : 243, // Break
IP : 244, // Interrupt Process
AO : 245, // Abort Output
AYT : 246, // Are You There?
EC : 247, // Erase Character
EL : 248, // Erase Line
GA : 249, // Go Ahead
SB : 250, // Start Sub-Negotiation Parameters
WILL : 251, //
WONT : 252,
DO : 253,
DONT : 254,
IAC : 255, // (Data Byte)
};
//
// Resources:
// * http://www.faqs.org/rfcs/rfc1572.html
//
var SB_COMMANDS = {
IS : 0,
SEND : 1,
INFO : 2,
};
//
// Telnet Options
//
// Resources
// * http://mars.netanya.ac.il/~unesco/cdrom/booklet/HTML/NETWORKING/node300.html
//
var OPTIONS = {
TRANSMIT_BINARY : 0, // http://tools.ietf.org/html/rfc856
ECHO : 1, // http://tools.ietf.org/html/rfc857
// RECONNECTION : 2
SUPPRESS_GO_AHEAD : 3, // aka 'SGA': RFC 858 @ http://tools.ietf.org/html/rfc858
//APPROX_MESSAGE_SIZE : 4
STATUS : 5, // http://tools.ietf.org/html/rfc859
TIMING_MARK : 6, // http://tools.ietf.org/html/rfc860
//RC_TRANS_AND_ECHO : 7, // aka 'RCTE' @ http://www.rfc-base.org/txt/rfc-726.txt
//OUPUT_LINE_WIDTH : 8,
//OUTPUT_PAGE_SIZE : 9, //
//OUTPUT_CARRIAGE_RETURN_DISP : 10, // RFC 652
//OUTPUT_HORIZ_TABSTOPS : 11, // RFC 653
//OUTPUT_HORIZ_TAB_DISP : 12, // RFC 654
//OUTPUT_FORMFEED_DISP : 13, // RFC 655
//OUTPUT_VERT_TABSTOPS : 14, // RFC 656
//OUTPUT_VERT_TAB_DISP : 15, // RFC 657
//OUTPUT_LF_DISP : 16, // RFC 658
//EXTENDED_ASCII : 17, // RFC 659
//LOGOUT : 18, // RFC 727
//BYTE_MACRO : 19, // RFC 753
//DATA_ENTRY_TERMINAL : 20, // RFC 1043
//SUPDUP : 21, // RFC 736
//SUPDUP_OUTPUT : 22, // RFC 749
//SEND_LOCATION : 23, // RFC 779
TERMINAL_TYPE : 24, // aka 'TTYPE': RFC 1091 @ http://tools.ietf.org/html/rfc1091
//END_OF_RECORD : 25, // RFC 885
//TACACS_USER_ID : 26, // RFC 927
//OUTPUT_MARKING : 27, // RFC 933
//TERMINCAL_LOCATION_NUMBER : 28, // RFC 946
//TELNET_3270_REGIME : 29, // RFC 1041
WINDOW_SIZE : 31, // aka 'NAWS': RFC 1073 @ http://tools.ietf.org/html/rfc1073
TERMINAL_SPEED : 32, // RFC 1079 @ http://tools.ietf.org/html/rfc1079
REMOTE_FLOW_CONTROL : 33, // RFC 1072 @ http://tools.ietf.org/html/rfc1372
LINEMODE : 34, // RFC 1184 @ http://tools.ietf.org/html/rfc1184
X_DISPLAY_LOCATION : 35, // aka 'XDISPLOC': RFC 1096 @ http://tools.ietf.org/html/rfc1096
NEW_ENVIRONMENT_DEP : 36, // aka 'NEW-ENVIRON': RFC 1408 @ http://tools.ietf.org/html/rfc1408 (note: RFC 1572 is an update to this)
AUTHENTICATION : 37, // RFC 2941 @ http://tools.ietf.org/html/rfc2941
ENCRYPT : 38, // RFC 2946 @ http://tools.ietf.org/html/rfc2946
NEW_ENVIRONMENT : 39, // aka 'NEW-ENVIRON': RFC 1572 @ http://tools.ietf.org/html/rfc1572 (note: update to RFC 1408)
//TN3270E : 40, // RFC 2355
//XAUTH : 41,
//CHARSET : 42, // RFC 2066
//REMOTE_SERIAL_PORT : 43,
//COM_PORT_CONTROL : 44, // RFC 2217
//SUPRESS_LOCAL_ECHO : 45,
//START_TLS : 46,
//KERMIT : 47, // RFC 2840
//SEND_URL : 48,
//FORWARD_X : 49,
//PRAGMA_LOGON : 138,
//SSPI_LOGON : 139,
//PRAGMA_HEARTBEAT : 140
EXTENDED_OPTIONS_LIST : 255, // RFC 861 (STD 32)
}
// Commands used within NEW_ENVIRONMENT[_DEP]
var NEW_ENVIRONMENT_COMMANDS = {
VAR : 0,
VALUE : 1,
ESC : 2,
USERVAR : 3,
};
var IAC_BUF = new Buffer([ COMMANDS.IAC ]);
var SB_BUF = new Buffer([ COMMANDS.SB ]);
var SE_BUF = new Buffer([ COMMANDS.SE ]);
var IAC_SE_BUF = new Buffer([ COMMANDS.IAC, COMMANDS.SE ]);
var COMMAND_NAMES = Object.keys(COMMANDS).reduce(function(names, name) {
names[COMMANDS[name]] = name.toLowerCase();
return names;
}, {});
var COMMAND_IMPLS = {};
['do', 'dont', 'will', 'wont', 'sb'].forEach(function(command) {
var code = COMMANDS[command.toUpperCase()];
COMMAND_IMPLS[code] = function(bufs, i, event) {
if(bufs.length < (i + 1)) {
return MORE_DATA_REQUIRED;
}
return parseOption(bufs, i, event);
}
});
// :TODO: See TooTallNate's telnet.js: Handle COMMAND_IMPL for IAC in binary mode
// Create option names such as 'transmit binary' -> OPTIONS.TRANSMIT_BINARY
var OPTION_NAMES = Object.keys(OPTIONS).reduce(function(names, name) {
names[OPTIONS[name]] = name.toLowerCase().replace(/_/g, ' ');
return names;
}, {});
var OPTION_IMPLS = {};
// :TODO: fill in the rest...
OPTION_IMPLS.NO_ARGS =
OPTION_IMPLS[OPTIONS.ECHO] =
OPTION_IMPLS[OPTIONS.STATUS] =
OPTION_IMPLS[OPTIONS.LINEMODE] =
OPTION_IMPLS[OPTIONS.TRANSMIT_BINARY] =
OPTION_IMPLS[OPTIONS.AUTHENTICATION] =
OPTION_IMPLS[OPTIONS.TERMINAL_SPEED] =
//OPTION_IMPLS[OPTIONS.TERMINAL_TYPE] =
OPTION_IMPLS[OPTIONS.REMOTE_FLOW_CONTROL] =
OPTION_IMPLS[OPTIONS.X_DISPLAY_LOCATION] =
OPTION_IMPLS[OPTIONS.SUPPRESS_GO_AHEAD] = function(bufs, i, event) {
event.buf = bufs.splice(0, i).toBuffer();
return event;
};
OPTION_IMPLS[OPTIONS.TERMINAL_TYPE] = function(bufs, i, event) {
if(event.commandCode !== COMMANDS.SB) {
OPTION_IMPLS.NO_ARGS(bufs, i, event);
} else {
// We need 4 bytes header + data + IAC SE
if(bufs.length < 7) {
return MORE_DATA_REQUIRED;
}
var end = bufs.indexOf(IAC_SE_BUF, 5); // look past header bytes
if(-1 === end) {
return MORE_DATA_REQUIRED;
}
// eat up and process the header
var buf = bufs.splice(0, 4).toBuffer();
binary.parse(buf)
.word8('iac1')
.word8('sb')
.word8('ttype')
.word8('is')
.tap(function(vars) {
assert(vars.iac1 === COMMANDS.IAC);
assert(vars.sb === COMMANDS.SB);
assert(vars.ttype === OPTIONS.TERMINAL_TYPE);
assert(vars.is === SB_COMMANDS.IS);
});
// eat up the rest
end -= 4;
buf = bufs.splice(0, end).toBuffer();
//
// From this point -> |end| is our ttype
//
// Look for trailing NULL(s). Client such as Netrunner do this.
//
var trimAt = 0;
for(; trimAt < buf.length; ++trimAt) {
if(0x00 === buf[trimAt]) {
break;
}
}
event.ttype = buf.toString('ascii', 0, trimAt);
// pop off the terminating IAC SE
bufs.splice(0, 2);
}
return event;
};
OPTION_IMPLS[OPTIONS.WINDOW_SIZE] = function(bufs, i, event) {
if(event.commandCode !== COMMANDS.SB) {
OPTION_IMPLS.NO_ARGS(bufs, i, event);
} else {
// we need 9 bytes
if(bufs.length < 9) {
return MORE_DATA_REQUIRED;
}
event.buf = bufs.splice(0, 9).toBuffer();
binary.parse(event.buf)
.word8('iac1')
.word8('sb')
.word8('naws')
.word16bu('width')
.word16bu('height')
.word8('iac2')
.word8('se')
.tap(function(vars) {
assert(vars.iac1 == COMMANDS.IAC);
assert(vars.sb == COMMANDS.SB);
assert(vars.naws == OPTIONS.WINDOW_SIZE);
assert(vars.iac2 == COMMANDS.IAC);
assert(vars.se == COMMANDS.SE);
event.cols = event.columns = event.width = vars.width;
event.rows = event.height = vars.height;
});
}
return event;
};
// Build an array of delimiters for parsing NEW_ENVIRONMENT[_DEP]
var NEW_ENVIRONMENT_DELIMITERS = [];
Object.keys(NEW_ENVIRONMENT_COMMANDS).forEach(function onKey(k) {
NEW_ENVIRONMENT_DELIMITERS.push(NEW_ENVIRONMENT_COMMANDS[k]);
});
// Handle the deprecated RFC 1408 & the updated RFC 1572:
OPTION_IMPLS[OPTIONS.NEW_ENVIRONMENT_DEP] =
OPTION_IMPLS[OPTIONS.NEW_ENVIRONMENT] = function(bufs, i, event) {
if(event.commandCode !== COMMANDS.SB) {
OPTION_IMPLS.NO_ARGS(bufs, i, event);
} else {
// We need 4 bytes header + payload + IAC SE
if(bufs.length < 7) {
return MORE_DATA_REQUIRED;
}
var end = bufs.indexOf(IAC_SE_BUF, 5); // look past header bytes
if(-1 === end) {
return MORE_DATA_REQUIRED;
}
// eat up and process the header
var buf = bufs.splice(0, 4).toBuffer();
binary.parse(buf)
.word8('iac1')
.word8('sb')
.word8('newEnv')
.word8('isOrInfo') // initial=IS, updates=INFO
.tap(function(vars) {
assert(vars.iac1 === COMMANDS.IAC);
assert(vars.sb === COMMANDS.SB);
assert(vars.newEnv === OPTIONS.NEW_ENVIRONMENT || vars.newEnv === OPTIONS.NEW_ENVIRONMENT_DEP);
assert(vars.isOrInfo === SB_COMMANDS.IS || vars.isOrInfo === SB_COMMANDS.INFO);
event.type = vars.isOrInfo;
if(vars.newEnv === OPTIONS.NEW_ENVIRONMENT_DEP) {
logger.log.warn('Handling deprecated RFC 1408 NEW-ENVIRON');
}
});
// eat up the rest
end -= 4;
buf = bufs.splice(0, end).toBuffer();
//
// This part can become messy. The basic spec is:
// IAC SB NEW-ENVIRON IS type ... [ VALUE ... ] [ type ... [ VALUE ... ] [ ... ] ] IAC SE
//
// See RFC 1572 @ http://www.faqs.org/rfcs/rfc1572.html
//
// Start by splitting up the remaining buffer. Keep the delimiters
// as prefixes we can use for processing.
//
// :TODO: Currently not supporting ESCaped values (ESC + <type>). Probably not really in the wild, but we should be compliant
var params = [];
var p = 0;
for(var j = 0, l = buf.length; j < l; ++j) {
if(NEW_ENVIRONMENT_DELIMITERS.indexOf(buf[j]) === -1) {
continue;
}
params.push(buf.slice(p, j));
p = j;
}
// remainder
if(p < l) {
params.push(buf.slice(p, l));
}
var varName;
event.envVars = {};
// :TODO: handle cases where a variable was present in a previous exchange, but missing here...e.g removed
for(var j = 0; j < params.length; ++j) {
if(params[j].length < 2) {
continue;
}
var cmd = params[j].readUInt8();
if(cmd === NEW_ENVIRONMENT_COMMANDS.VAR || cmd === NEW_ENVIRONMENT_COMMANDS.USERVAR) {
varName = params[j].slice(1).toString('utf8'); // :TODO: what encoding should this really be?
} else {
event.envVars[varName] = params[j].slice(1).toString('utf8'); // :TODO: again, what encoding?
}
}
// pop off remaining IAC SE
bufs.splice(0, 2);
}
return event;
};
var MORE_DATA_REQUIRED = 0xfeedface;
function parseBufs(bufs) {
assert(bufs.length >= 2);
assert(bufs.get(0) === COMMANDS.IAC)
return parseCommand(bufs, 1, {});
}
function parseCommand(bufs, i, event) {
var command = bufs.get(i); // :TODO: fix deprecation... [i] is not the same
event.commandCode = command;
event.command = COMMAND_NAMES[command];
var handler = COMMAND_IMPLS[command];
if(handler) {
//return COMMAND_IMPLS[command](bufs, i + 1, event);
return handler(bufs, i + 1, event);
} else {
assert(2 == bufs.length); // IAC + COMMAND
event.buf = bufs.splice(0, 2).toBuffer();
return event;
}
}
function parseOption(bufs, i, event) {
var option = bufs.get(i); // :TODO: fix deprecation... [i] is not the same
event.optionCode = option;
event.option = OPTION_NAMES[option];
return OPTION_IMPLS[option](bufs, i + 1, event);
}
function TelnetClient(input, output) {
baseClient.Client.apply(this, arguments);
var self = this;
var bufs = buffers();
this.bufs = bufs;
var readyFired = false;
var encodingSet = false;
this.negotiationsComplete = false; // are we in the 'negotiation' phase?
this.didReady = false; // have we emit the 'ready' event?
this.input.on('data', function onData(b) {
bufs.push(b);
var i;
while((i = bufs.indexOf(IAC_BUF)) >= 0) {
// :TODO: Android client Irssi ConnectBot asserts here:
assert(bufs.length > (i + 1), 'bufs.length=' + bufs.length + ' i=' + i + ' bufs=' + bufs);
if(i > 0) {
self.emit('data', bufs.splice(0, i).toBuffer());
}
i = parseBufs(bufs);
if(MORE_DATA_REQUIRED === i) {
break;
} else {
//self.emit('event', i); // generic event
//self.emit(i.command, i); // "will", "wont", ...
if(i.option) {
self.emit(i.option, i); // "transmit binary", "echo", ...
}
self.handleTelnetEvent(i);
if(i.data) {
self.emit('data', i.data);
}
}
}
if(MORE_DATA_REQUIRED !== i && bufs.length > 0) {
//
// Standard data payload. This can still be "non-user" data
// such as ANSI control, but we don't handle that here.
//
self.emit('data', bufs.splice(0).toBuffer());
}
});
this.input.on('end', function() {
self.emit('end');
});
}
require('util').inherits(TelnetClient, baseClient.Client);
///////////////////////////////////////////////////////////////////////////////
// Telnet Command/Option handling
///////////////////////////////////////////////////////////////////////////////
TelnetClient.prototype.handleTelnetEvent = function(evt) {
// handler name e.g. 'handleWontCommand'
var handlerName = 'handle' + evt.command.charAt(0).toUpperCase() + evt.command.substr(1) + 'Command';
if(this[handlerName]) {
// specialized
this[handlerName](evt);
} else {
// generic-ish
this.handleMiscCommand(evt);
}
};
TelnetClient.prototype.handleWillCommand = function(evt) {
if('terminal type' === evt.option) {
//
// See RFC 1091 @ http://www.faqs.org/rfcs/rfc1091.html
//
this.requestTerminalType();
} else if('environment variables' === evt.option) {
//
// See RFC 1572 @ http://www.faqs.org/rfcs/rfc1572.html
//
this.requestEnvironmentVariables();
} else {
// :TODO: temporary:
console.log('will ' + JSON.stringify(evt));
}
};
TelnetClient.prototype.handleWontCommand = function(evt) {
console.log('wont ' + JSON.stringify(evt));
};
TelnetClient.prototype.handleDoCommand = function(evt) {
// :TODO: handle the rest, e.g. echo nd the like
if('linemode' === evt.option) {
//
// Client wants to enable linemode editing. Denied.
//
this.wont.linemode();
} else if('encrypt' === evt.option) {
//
// Client wants to enable encryption. Denied.
//
this.wont.encrypt();
} else {
// :TODO: temporary:
console.log('do ' + JSON.stringify(evt));
}
};
TelnetClient.prototype.handleDontCommand = function(evt) {
console.log('dont ' + JSON.stringify(evt));
};
TelnetClient.prototype.setTermType = function(ttype) {
this.term.env['TERM'] = ttype;
this.term.termType = ttype;
logger.log.debug({ termType : ttype }, 'Set terminal type');
}
TelnetClient.prototype.handleSbCommand = function(evt) {
var self = this;
if('terminal type' === evt.option) {
//
// See RFC 1091 @ http://www.faqs.org/rfcs/rfc1091.html
//
// :TODO: According to RFC 1091 @ http://www.faqs.org/rfcs/rfc1091.html
// We should keep asking until we see a repeat. From there, determine the best type/etc.
self.setTermType(evt.ttype);
self.negotiationsComplete = true; // :TODO: throw in a array of what we've taken care. Complete = array satisified or timeout
if(!self.didReady) {
self.didReady = true;
self.emit('ready');
}
} else if('new environment' === evt.option) {
//
// Handling is as follows:
// * Map 'TERM' -> 'termType' and only update if ours is 'unknown'
// * Map COLUMNS -> 'termWidth' and only update if ours is 0
// * Map ROWS -> 'termHeight' and only update if ours is 0
// * Add any new variables, ignore any existing
//
Object.keys(evt.envVars).forEach(function onEnv(name) {
if('TERM' === name && 'unknown' === self.term.termType) {
self.setTermType(evt.envVars[name]);
} else if('COLUMNS' === name && 0 === self.term.termWidth) {
self.term.termWidth = parseInt(evt.envVars[name]);
} else if('ROWS' === name && 0 === self.term.termHeight) {
self.term.termHeight = parseInt(evt.envVars[name]);
} else {
if(name in self.term.env) {
assert(evt.type === SB_COMMANDS.INFO);
logger.log.warn(
{ varName : name, value : evt.envVars[name], existingValue : self.term.env[name] },
'Environment variable already exists');
} else {
self.term.env[name] = evt.envVars[name];
}
}
});
} else if('window size' === evt.option) {
//
// Update termWidth & termHeight.
// Set LINES and COLUMNS environment variables as well.
//
self.term.termWidth = evt.width;
self.term.termHeight = evt.height;
if(evt.width > 0) {
self.term.env['COLUMNS'] = evt.height;
}
if(evt.height > 0) {
self.term.env['ROWS'] = evt.height;
}
logger.log.debug({ termWidth : evt.width , termHeight : evt.height }, 'Window size updated');
} else {
console.log('unhandled SB: ' + JSON.stringify(evt));
}
};
var IGNORED_COMMANDS = [];
[ COMMANDS.EL, COMMANDS.GA, COMMANDS.NOP, COMMANDS.DM, COMMANDS.BRK ].forEach(function onCommandCode(cc) {
IGNORED_COMMANDS.push(cc);
});
TelnetClient.prototype.handleMiscCommand = function(evt) {
assert(evt.command !== 'undefined' && evt.command.length > 0);
//
// See:
// * RFC 854 @ http://tools.ietf.org/html/rfc854
//
if('ip' === evt.command) {
// Interrupt Process (IP)
logger.log.debug('Interrupt Process (IP) - Ending');
this.input.end();
} else if('ayt' === evt.command) {
this.output.write('\b');
logger.log.debug('Are You There (AYT) - Replied "\\b"');
} else if(IGNORED_COMMANDS.indexOf(evt.commandCode)) {
logger.log.debug({ evt : evt }, 'Ignoring command');
} else {
logger.log.warn({ evt : evt }, 'Unknown command');
}
};
TelnetClient.prototype.requestTerminalType = function() {
var buf = Buffer([ COMMANDS.IAC, COMMANDS.SB, OPTIONS.TERMINAL_TYPE, SB_COMMANDS.SEND, COMMANDS.IAC, COMMANDS.SE ]);
/*
var buf = Buffer(6);
buf[0] = COMMANDS.IAC;
buf[1] = COMMANDS.SB;
buf[2] = OPTIONS.TERMINAL_TYPE;
buf[3] = SB_COMMANDS.SEND;
buf[4] = COMMANDS.IAC;
buf[5] = COMMANDS.SE;
*/
return this.output.write(buf);
};
var WANTED_ENVIRONMENT_VARIABLES = [ 'LINES', 'COLUMNS', 'TERM' ];
TelnetClient.prototype.requestEnvironmentVariables = function() {
var bufs = buffers();
bufs.push(new Buffer([ COMMANDS.IAC, COMMANDS.SB, OPTIONS.NEW_ENVIRONMENT, SB_COMMANDS.SEND ]));
for(var i = 0; i < WANTED_ENVIRONMENT_VARIABLES.length; ++i) {
bufs.push(new Buffer( [ ENVIRONMENT_VARIABLES_COMMANDS.VAR ]));
bufs.push(new Buffer(WANTED_ENVIRONMENT_VARIABLES[i])); // :TODO: encoding here?! UTF-8 will work, but shoudl be more explicit
}
bufs.push(new Buffer([ COMMANDS.IAC, COMMANDS.SE ]));
return this.output.write(bufs.toBuffer());
};
TelnetClient.prototype.banner = function() {
// :TODO: See x84 implementation here.
// First, we should probably buffer then send.
this.will.echo();
this.will.suppress_go_ahead();
this.do.suppress_go_ahead();
this.do.transmit_binary();
this.will.transmit_binary();
this.do.terminal_type();
this.do.window_size();
this.do.new_environment();
}
function Command(command, client) {
this.command = COMMANDS[command.toUpperCase()];
this.client = client;
};
// Create Command objects with echo, transmit_binary, ...
Object.keys(OPTIONS).forEach(function(name) {
var code = OPTIONS[name];
Command.prototype[name.toLowerCase()] = function() {
var buf = Buffer(3);
buf[0] = COMMANDS.IAC;
buf[1] = this.command;
buf[2] = code;
return this.client.output.write(buf);
}
});
// Create do, dont, etc. methods on Client
['do', 'dont', 'will', 'wont'].forEach(function(command) {
function get() {
return new Command(command, this);
}
Object.defineProperty(TelnetClient.prototype, command, {
get : get,
enumerable : true,
configurable : true
});
});
function createServer() {
var server = net.createServer(function onConnection(sock) {
var self = this;
var client = new TelnetClient(sock, sock);
client.banner();
self.emit('client', client);
});
return server;
};

11
main.js Normal file
View File

@ -0,0 +1,11 @@
"use strict";
var net = require('net');
var fs = require('fs');
var paths = require('path');
// ENiGMA½
var bbs = require('./core/bbs.js')
// The entry point.
bbs.bbsMain();

12
misc/default_key.dsa Normal file
View File

@ -0,0 +1,12 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBugIBAAKBgQDA9HhqZZrq167Vz/AJECJGjJB0DKu72Qji0HfZxDBw/mrsRh89
W/0LQSIOBROIGczGyxuelUAwQxzx5sN3LBABPGutKat4FbxsKO5Ix6VODt5gmT82
eyXm9XpV49EDRoO3AxZJoc+Fmiy7meqtAoGNG9Y4K7fRsq9NTNMgt5w4RQIVAIDp
xj5whr2w95anI/UBs9GPvodpAoGABzR9OqO/yrgOmjq+vg6+T+RRQNB7dRjfsY9A
NJFKC15ZNsLFXJSyKV067GW/6AYYaqJokz93ZS/azuNRm4GesbvIltri3MXZ0cRF
m9zazKS4OlCwCySBIai4Hjv4oNSV+hiYqEsNYA8fubP9fILXioD0ojwIC7tJam9d
UTPOhNMCgYAh8P2Cu6hE6qJy9NToeaimRcIT3UCqnqORWrelOymmrX2v9wboB2DB
Ehm4RpJhPps8NnxIg4fDxARqBVpgAkizfWlzdJMw5JFz3qm5To7MMD4AJ9ZbtpHE
uTGglej7v5jTM+qk6hlB5mNgvqHgtKkyLLMZz2PTzRo1+bJ6bA0c2AIUFUxwM+1H
zd9qN20heajSqKqiZ4g=
-----END DSA PRIVATE KEY-----

1
misc/default_key.dsa.pub Normal file
View File

@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAMD0eGplmurXrtXP8AkQIkaMkHQMq7vZCOLQd9nEMHD+auxGHz1b/QtBIg4FE4gZzMbLG56VQDBDHPHmw3csEAE8a60pq3gVvGwo7kjHpU4O3mCZPzZ7Jeb1elXj0QNGg7cDFkmhz4WaLLuZ6q0CgY0b1jgrt9Gyr01M0yC3nDhFAAAAFQCA6cY+cIa9sPeWpyP1AbPRj76HaQAAAIAHNH06o7/KuA6aOr6+Dr5P5FFA0Ht1GN+xj0A0kUoLXlk2wsVclLIpXTrsZb/oBhhqomiTP3dlL9rO41GbgZ6xu8iW2uLcxdnRxEWb3NrMpLg6ULALJIEhqLgeO/ig1JX6GJioSw1gDx+5s/18gteKgPSiPAgLu0lqb11RM86E0wAAAIAh8P2Cu6hE6qJy9NToeaimRcIT3UCqnqORWrelOymmrX2v9wboB2DBEhm4RpJhPps8NnxIg4fDxARqBVpgAkizfWlzdJMw5JFz3qm5To7MMD4AJ9ZbtpHEuTGglej7v5jTM+qk6hlB5mNgvqHgtKkyLLMZz2PTzRo1+bJ6bA0c2A== ENiGMA½ Default DSA Key

27
misc/default_key.rsa Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAns9TDs2FY3dXmGtE5a3tu5GS3I9/O9a9NU1yPrcuwhXgOL3D
hPYjbWT8ypKZyMMwdRNxmfnXNQjooBt2CdcVjezrWPTfexQRNNEfcQ7JmUPKrtQQ
ZZRU+ubFMycgNyDt3w3SwgisBFcb9qiFj1Y12jpKpkvnB+HtuV5HA0XODoI4OA93
mef02q+rbHfyT3EDlwBLJcZiew/ALlOiB/bACHXkYoal979HRTV4aW8Xx2WxstLD
bBaZSuQJQFNLR2DsivHHs0JlxcO4D6oBiw8mTr1SRrunDldmndCYPp66gpsJf+7B
5PwrQ20hOG+UEp7CReBvX4y7AD2TP6nKjJ96EQIDAQABAoIBADQtMcC/TX/sid8N
/0jm6CCkJ3hHvSnP18JXe52XWclynoSF9GMO63zZnSSBHf2UA6uzg7NvHoHSN3vD
CfkZrX8/w+MqMPKjGTQdMRNYJGwylbjy+6AkJ/d3Mnsn87GpI/4Q8JnHd5zFce6M
V7VMQc09MaGJdpJkbFJm4zX0DUs+gN2liq+lOQWVBBY3baAS9ZhDGAnxgDzCteRQ
lJYbKbO4MqwNvzKRgUjCNMpf28tUXu1JzK7NosQ0eA8yz3il8MQuD7+1Kmaxrkhv
/FhV9GaVod4HB7iwVyM4cvwXDGtMg8W0IU6aaqmctWvEckCnImuqRrzxseeAQA8K
fgTeIwECgYEA0Q38Rk1SryCMKtJZisQCwsNN8eFs7tT9QhpJxQG4JsJtjid4q+Ze
YMOVDwSdlsPu3XPGql/88mawjOSQLw2bQ9kOOjm3/1G1XoKqCajmWyvYznLc22/b
wN3zeubkk2/PHPP8h43WZCLxnfbMGyEXxCmOZYz/AIv3CKlA5KnM9ZkCgYEAwnjl
ZB+kh8AnejDhcCiNbk0Bt8xYMHiewSU5jW3sCrXpcZ7fPLERJhxiMEVT7WfnIdb7
z1OZOqEnl+XhqGIJRLRgM2FrFSHgWbdATcSNLYaMVrMwGOcaHB/Ww2ffVhRa2B5H
16yol6oeya7OubQE+4JeqPU3thCR+OGFCgl8AzkCgYAgLr/8bqDg9ui9Gt7P/vbR
1tEkAGkNp1pJl9RtcKNRzDKjZK4uAGvdB57lzfcYo5cdHlqiFd7Rzj81oWYU6EpT
upF3IzWRJ5n9L65PiGHV/T0GIyae3Wx+F20JKYxcqiS/N0xT7eDoT3zUrY6kSobn
GuKh/X+wLNvdyHiF+yHjWQKBgEWn6/Iq61G8X+eCbp0vyUjCyGS/Cq+B5MslvDGO
N8e2VMFfuHISsiPGctz7WA5m8wDJ8jPWq8G2S2o66tLXGp7DRNnigOp20dcQrjWs
uyydTtMXJ5kj3dRJCzG+mN5KOCfE4NK9gz2fr5tpw538fvRfQ+ycuLG7ya0tieuI
biTxAoGAZAglKOHJIqLXoBPT3GH2nDl0BDEJ/3Ob7g54nupz753LO/6MlFGGX7Cg
X360g9Snk08+pYDos6ayT/vmeegbqfV7A+1sXHsGGuYyaLSkTjdcIUV/eF5h/HbE
CnRfXZe2jsFzYNK835BcYIndDIElyW6jipkgkwwWCOMqPC9Ulto=
-----END RSA PRIVATE KEY-----

1
misc/default_key.rsa.pub Normal file
View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCez1MOzYVjd1eYa0Tlre27kZLcj3871r01TXI+ty7CFeA4vcOE9iNtZPzKkpnIwzB1E3GZ+dc1COigG3YJ1xWN7OtY9N97FBE00R9xDsmZQ8qu1BBllFT65sUzJyA3IO3fDdLCCKwEVxv2qIWPVjXaOkqmS+cH4e25XkcDRc4Ogjg4D3eZ5/Tar6tsd/JPcQOXAEslxmJ7D8AuU6IH9sAIdeRihqX3v0dFNXhpbxfHZbGy0sNsFplK5AlAU0tHYOyK8cezQmXFw7gPqgGLDyZOvVJGu6cOV2ad0Jg+nrqCmwl/7sHk/CtDbSE4b5QSnsJF4G9fjLsAPZM/qcqMn3oR ENiGMA½ Default RSA Key

BIN
mods/art/CONNECT1.ANS Normal file

Binary file not shown.

19
mods/art/DM-ENIG.ANS Normal file
View File

@ -0,0 +1,19 @@
 ーーーーーーーーーワイワワ  ー  ワワ 
 ーーーーーー ワワ゚ロロロイロロロロロ゚  ーー  ーーー ーーーー ー ワワワ゚゚゚ワワイロロロロロ゚
ーワワワ゚゚゙ロロロロイイロン ーー  ワワワ ワワ ーワワワ゚゚ロイイロロン
゚ワワワロロロイロ  ーロロロイイイアアワワワ゚゚ロロロロイロ゚ロイイイイアワワワイイイイーー ーー゙ロロロロロイ
 ゙ロイイロロロン゙ロイイアアアーン イアワワーア゚ ゙イイイイロン ゙イイアアアアアイイイアアア゙イイロロロン
ロロロロイイ゚     イイアアーーーロロー ーーーーン  アアアイイ イイアアーー ーアアアーーーーアアイイロン  
ーーイロイイアーーーー ー  ゚゚゚ーーロロヷーーーーアアーー ーー ーー ーーアア ゙ ーアーーーー゙ ーーーーーーー ーー ー ーーーーーアアイーー   ー゙イアアーー ワワ    ーーアアイロ  ゙アアーーー  ーーーアア ゙ーーーーアン ワ ゙ロ ーーアア 
ワ ゙アーー ーーン  ワ ワロロワワワ ワロイイイロロン゙ワイ゚ ゙ロイイアーー ーーアアアア ワ アアアアイロ ゙ロワロロイロ ゙ロロロロー  ゙ワ 
ーン ー ーーアイン ーーロワ ロロイイロロロロロロイロロイン ーー ゚゚゚゚ロイアア゚゙アアイイ ゙ーン ロイイロロン ローーロロン ーーーーロロン ロロー
゚  ーーーアアイイ ゚゚イ゚ ゙ロロロロロロイロロロロロロイ ゚゚゚イ ゚゚ イイロン ゚イ゚ ゙ロイロイイ ワワワ ゚ ゙アアーーーン ゚イ゚
゙アアアイイロン  ロロロロロロロロロロロロロロ゚゚ロロイロ゚゚ ゚゚゚゚゚ ロイイアアアア
ロイイロロロロ ゙ロロロロロイロ ロ゚゚ ゙イワロロイイイロン
 ワワ゚゚ ゚゚゚ワワワ ロロロロイ゚ ワワロロロロ゙ロロイロロ 
 ーー ゚゚゚゚゚ーーー ーー enigmaォbbs softロロロイイロンー ゙ロロロロイ ーー
dangermouse ーーロイロロロロロイロイロ ー
  ーー  ロイロロロロワワワワ゚゚゚゚゚゚゚゚ワワワ
゙ロロ゚゚ーーーーー
 ー ゚ ーーーーーーーーーー


19
mods/art/DM-ENIG.PCB Normal file
View File

@ -0,0 +1,19 @@
@X0F @X04ーーーーーーーーー @X0Fワイワワ @X0Eー @X0Fワワ
@X0F @X04ーーー@X4Fー@X04ーー @X0Fワワ゚ロロロイ@X7Fロ@X4Fロロ@X0Fロロ゚ @X07ーー @X0Eーーー ーーーー ー @X0Fワワワ゚゚゚ワワイロロロロロ゚
@X0F @X04ー @X0Fワワワ゚゚ ゙ロ@X7Fロロロ@X4Fイイ@X0Fロン @X07ーー @X0Fワワワ ワワ @X0Eー@X0Fワワワ゚゚ ロ@X4Fイイ@X0Fロロン
@X0F゚ワワワロ@X7Fロロ@X0Fイロ @X04ー @X0Fロ@X7Fロロイイイアア@X0F ワワワ゚゚ロロロロ@X4Fイロ@X0F゚ ロイ@X7Fイイイア@X0Fワワワイ@X7Fイイイ@X0Fーー ーー ゙ロロロロロイ
@X0F ゙@X7Fロ@X4Fイイ@X7Fロロロ@X0Fン ゙ロ@X7Fイイアアアー@X0Fン @X7Fイア@X0Fワワ@X7Fーア@X0F゚ ゙@X7Fイイイイロ@X0Fン ゙@X7Fイイアアアアアイイイアアア@X0F ゙@X7Fイイ@X0Fロ@X4Fロ@X0Fロン
@X0F @X7Fロロロロイイ゚@X07 @X7Fイイアアーーー@X07ロロ@X7Fー ーーー@X78ー@X07ン @X78 @X7Fアアアイイ@X08 @X7Fイイアアーー ーアアアーーー@X0F @X7Fーアアイイロ@X0Fン
@X0Fーーイロ@X7Fイイアーー@X0Fーー ー @X07゚゚゚@X7Fーー@X07ロロヷ@X7Fーー@X78ーーアア@X0Fーー ーー ー@X7Fー ーーアア @X07゙@X7F ーアー@X78ーーー@X07゙@X7F ーー@X78ーーー@X0Fーー ーー ー ーー@X7Fーーーアアイ@X0Fーー
@X0F ー゙@X7Fイアアーー @X07ワワ @X78ーーアアイ@X08ロ ゙@X78アアーー@X7Fー @X78ー@X7Fー@X78ーアア@X08 @X07゙@X7Fー@X78ーーーア@X08ン @X01ワ @X07゙ロ@X7F ーーアア@X07
@X01ワ @X07゙@X7Fアーー @X78ーー@X08ン @X01ワ @X08ワロロワワワ ワロ@X78イイイ@X08ロロン@X01゙ワイ゚ @X08゙ロ@X78イイアーー ーーアアアア@X07 @X01ワ @X78アアアアイ@X08ロ @X01゙ロワロロイロ @X07゙ロロロロ@X7Fー @X07 @X01゙ワ
@X19ー@X01ン @X7Fー @X78ーーアイ@X08ン @X19ーー@X01ロワ @X08ロロ@X78イイ@X08ロロロロロロ@X78イ@X08ロロイン @X19ーー@X07 @X08゚゚゚゚ロ@X78イアア@X08゚゙@X78アアイイ@X08 @X01゙@X19ー@X01ン @X08ロ@X78イイロ@X08ロン @X01ロ@X19ーー@X01ロロン @X78ーーーー@X07ロロン @X01ロロ@X19ー@X07
@X01゚ @X78ーーーアアイイ@X08 @X01゚゚イ゚ @X08゙ロロ@X78ロロ@X08ロロイロロロロロロイ @X01゚゚゚イ ゚ @X08゚ @X78イイ@X08ロン @X01゚イ゚ @X08゙ロイロイイ ワワワ @X01゚ @X08゙@X78アアーーー@X07ン @X01゚イ゚
@X01 @X08゙@X78アアアイイ@X08ロン ロロロロロロロロロロロロロロ゚゚ ロロイ ロ゚゚ ゚゚゚ ゚゚ ロ@X78イイアアアア@X07
@X0F @X08ロ@X78イイロロロ@X08ロ ゙ロロロロロイロ ロ゚゚ ゙イ ワ ロロ@X78イイイ@X08ロン
@X08 ワワ゚゚ ゚゚゚ワワワ ロロロロイ゚ ワワロロロロ ゙ロ@X78ロイ@X08ロロ
@X08 ーー ゚゚゚゚゚ @X0Cーーー ーー @X0Feni@X4Fg@X0Fmaォ @X07bbs soft @X08ロロロ@X78イイ@X08ロン @X04ー @X08゙ロロロロイ @X04ーー
@X08dangermouse ーー ロイロロロロ ロ@X78イロ@X08イロ @X04ー
@X04 @X08ーー ロイロロロロワワワワ゚゚゚゚゚゚゚゚ワワワ
@X08 ゙ロロ゚゚ @X04ー@X4Fー@X04ーーー
@X04 @X08ー ゚ @X04ーーーーーーーーーー

Binary file not shown.

21
mods/art/DM-ENIG2.ANS Normal file
View File

@ -0,0 +1,21 @@
  ° ÜÜÛÛÛÛÜÜ
°  ° ÛÛ ÛßßÛÛÛÜÜÜÛ²Ûßßþ °
° ÜÜÜ  ÜÞÛÛÛÛÛ ÛÛÛÝ Û²²²²²ßÛÛÜÜ  °
 ÛÛ²²² þßß²²±°ÜÜÝ ÜÜÛÜ ßÛÛÛÛß Ü  ÜÜܲ²²±±±±Þ²²²Û
 Þ²²±±±Ý±ßß²²ßþ±²ß þßßÛÛ²Ü ßßÛÜÛßß ÜÜܲÛÛ²ßßþ ÜÛ²²²²±±°°°Ý °±±²²Ý
 Û²±°°°° °°°  Ü Ü Ü °  Þ²±±ÛÜܲÜÜÛ ²±±²²Ý  °°  ²±±±°°°° ÛÛ  °°° Þ°°°±±  
  ±°ß ß °°°  ²²ßÜÛßß²²ß²Ý °° ±±°°°°ÛÛÛÛ°°°°±±  °°°° Þ±°°°ß ßß²ßß °  ß²°ßß  °
°  ÜÜÜ²Ü   Üܲ Û²ßß ÛÛÛ°Ûß ° Þ °° Û ±±Û²Û°°°°Û  °°°  ßß Ü °° °  Ü²Ü ÜÜ  °°
°°  Û²Ûßß ßßß ÜÜ Û²ÛÛß   Û±²ßß ÞÛÛ²²ÛÛßß° ÜÜÜÜ   ²ÜÜ²ß  °°°°  ²ßÛßß²ß  °° 
 ÛÛ²ÛÛÛÜÜÜÜÛ ²²Û ß² ß ÛÛÛÛßÝ ß²ß ßÛÛ²Û   ÞÛ²²ÛÛÝ
  °° ßßß²ßß ß  °°  ßßß  °°  ÜÜÛÛÛ²²Û  °°  ßß²ßß  °°
±±±±±°°° °°°±±±±±±±±  ±± ±±±± ßßß  ±±±±   ÜÛÛÜÜ ±±±±
²²²²²²²²²²²²²²²² ²²²²²² ²²²²²²²²²²²²²²²²²²²   ß²Û  ²²² ß ßß  ßßßß  ßßßß 
ÜÜÜÜÜÝdangermouse help c²²o  mm a n d shelp
ß ßßßß
ESC - Exit ENiGMA« F3 - Configure
SPC - Logon Local °F4 - User Editor
F1  - Init Modem °F5 - DOS Shell
F2  - Hangup Modem F6 - Review Logs


551
mods/art/IC-CS.ANS Normal file
View File

@ -0,0 +1,551 @@


ÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜ
Û°°°°°°Û° Û°°°°°°°
Û°
ßß²±±²ßß° ²±±²
ßßßßß°
ßßÝ ßßݱ²²±° 
±²²±°
±Ü±±±°°°°
° °°°°°°
ß ß ß ß±±±±° 
±±±±°°
°°Üܲ²²²ÜÜ ²²²
²ÜÜÜÜÜ°
°°ÛÛÛÛÛÛÛÛ° Û
ÛÛÛÛÛÛÛÛ°°
ßßßßßßßß° ßßßßßßßßß°°
°ßßÝ ßßÝ ßßÝ ßßÜ Û Ý ßßß ßßß ßßß ßßÝ ßßÝ
±±
ÜÜÜÜܱßß ±±ß ±±
±±±±±±±±±
±±°°
ßßßßßßßÛÜÜß ß ß ßßß ßß ßßß ßßß ß ßßß ßßß ß ß°
ßß°°±Ü
ßßÜ°°°°°²±
ÜÜÜÜÜÜÜÜ°°±²Û
ÜÛÛßßßßß ßßß Ü°°°°±°²Ý
ß°°°±Þ° °²Ý
ÜÜÛßß ÜÜ °°°°°±Ý ²²±±²
²
ܲßß °° ° °°±Ý ° ±Ý Û²²°
²Ý±
ÜÜÜßß ²²ÜÜÜÜÜÜܲ²²ÜÜ ° ° ±±² °
°°Ý Þ²± ÞÛ²Û Ý ²Û°
ß²²ÝßßßÜܲ²ßß ßßÛÜ °°
± ²ÛÝ °±± Û²² Û²ÛÝ Û ²±Ý ° 
 ß
ÜÜß ÜÜܲßܲ²ßß ÜÜ ßßÜÜ ß ±±² Þ²
Û ±²ÝÞ²Þ²Ý Þ²±²ÝÞ °±²± Üß
 Ü
ÜÜßßÜܲ²ßßßÜ²ß ßßÜ ßß ß²Ü ß ²²Û Þ²
Ý ²ÛݲÝÞ²Ý ²
±°±Ý ±°±Ý Ü ² Üß Ü²²
ß
ÛßÜÛßß ÜÛß ÜÜÜ ÜÜ°°°Ü ßÜ Û²
Û²±±Þ²Û²Ý ²²
Þ±°°ÝÞ ²²±ß ÜÜÜÜ ÜÜ
²ß
ÜÛß ²²ÜÛßÜßß Ü Ü²±±ßß ßß
°Ü Üܲ²Ü Þ²Ý
ß°ÝÞ±²Þ²Û²²±
°±Ý ²ßÜܲ²Ûßß Ü
Ûß
ßÜÜÞ²ÜÛß ÜÜßܲ²ßÜÜÛßß
ÜÜ Ü²²ßÜßßÛÜ ²ÝÞ
±°±ÛÞ²Þ±±²
ܲ²ßßÜÜß ÜÛß Ü Üß
°°ÝÞ ÛßÜ°°ܲßÜ
²²ßÜ²ß ßßÜ Û²ß ßß
±Ü ß ÛݲÝÞ±
ÝÞ ÞÝÛ²±Ü²²ß ÜßßÜÜß Üßß ÜÜßß
 °
°°°Û °°°Û²ÝÞ²ß 
²²ßܱ Û²ßÜß Ü ßÜ Þ
 Û Û²²Þ Þ ²ÛÜ²ß ßÜ
Üß ÜÜÜÛßß ÜÜ°±²Ü
°°Û °°°Û²ÝÞ²Ý 
²²° ßÞ± Û²Ýß Ü ßÜ
 Þ Ý ²ÝÞ²ÝÞÛ ÜÜßßß Ü ß
²ßß ÜÜß°±
°ÝÛ ÝÞ°Û²ÝÞ
²Ý ²²°°ÝÞ±ÝÞ
²Û ±±²²ÜÜÜ ß ßÞ Û 
²Ý Þ Üß ßßÛÜßÜ ÜÜ ß ÜÜÜܲ²²²ß
°ÞÝÞÝ°ÝÞ²ÝÞ²Ý 
²²°°ÝÞ²Ý Û²
ÝÞÞ±±±±±±±²²²ÜÜÜÜÛ ÞÝ ÛÝ
ÜÜÜ ÞÝßß²²ÜÜ ÜÜÜÜÜÜ
°ÞÞÜßÞÞ²ÝÞ²
Ý ²²ÝÝ°°²²Þ
Þ²ÝÞ±Þ°±±°ß°°°°
°±²Û²ÝÛ Ý Ûß ÜßßÜ
Ü ÜÜ ²ÞÛÜ ßß²Ü ÜÜÜßß
ÝÝ°°°Ý²ÝÞ²ÝÞ
Þ²ÝÞÝ°²Û Ý
Û²Þ޲ݰ°±°°°±
°°°°±²Û²ÝÝÝÞß Ü 
±° °²ÝÞÝß²Ü ÜßßÜ ßß
ÛÞ°°°Þ²Þ²ÝÞÝ
²²ÛÞ Þ²Ý°Þ
²Ý°Ý²Ý°°±
°°±±±°°°²Û²Ý ß ÜßÜ Ü
ßÞ±°°°ÛÞ² ²
Þ ±Ý ÜßÜÜßÜ
ßÛ
°°°°Ý²ÝÛÛÞ
°Þ²ÝÝÞ ÝÛ²Þ
 ۲ݰ°Þ²Þ
°°°°±±±°°°²Û²Û ÞÝ
 ±° °°ÝÝÞݲÞ
Û ° ÞÝ°ß Û
°°°°ÝÛ޲ݱÝ
Û²Û ²Þ² ÝÝ
²ÛÞ°°Þ²Þ
°°°±±±°°°²Û²ÝÝ
Û ±° °°±ÝݲÞÝÛ
Û °ÞÞÜ°ß 
Û
°°°°ÞÝÛÛÞ²Ý
²ÝÛݲÝÛÝ°ÞÞ
²ÛÞ°°ÝÛÝ
°°°±²±°°°²Û²Ý
Û Þ±° °°±±Û Þ
ÝÛÝÝ° ²²²°Þ
 
°°±±ÞÞÛݲ²ÞÛÝÛÞ
²ÞÛÞÝÝ޲ݰ°°°
ÞÛÞ±±²²°°°²Û
²ÝÞÞÝÜß
° °°±±±ÛÞÞÝÛÛÛ 
°Þ±±²Û 
±±²²ÝÛÛÞÞ±Þ
²ÞݲÝÛÝ°ÝÝÞÛÝ
°°°°ÝÞݱ±²²°°°²
²±ÞÞÝ²Û  
°°±±²ÛÞݲÛÝ
Ý °°±±Û
²²²²ÞÛÝÛÞ°Þ
²ÞÝÛ ÛÝ°Þ ²Ý
°Û°°°Û ²²°°
°²²±ÝÞ Û 
²Û °°±±Ýݲݲ
ÞÞÛÞÝ Þ±°°±
Þ
²±±ÝÛÛÞÝ°ÝÛÝ
ÛÝÝÞÛÞ°Þ Ý²
Ý° Û°°°Û 
²°°°²²±Þ ÛÞ 
²Ý°°±±ÝݲÝ
²ÞÝÛÞÝÝ ±±±°±
±°°Þ²ÝÛÝ°ÝÛÝÛÝÞÞ
ÛÞÝÝÝÛÞÛÞ
°Û°°±±Üß ß
°²²±ÝÝ ÞÝ°²
Þ°±±ÛÞ² ²² Û
Þ²Þ±²±°
°ÛÛÞ²ÞÛÞ°Ý
ÛÝÛÞÞÞÛÞÝ
Ý°ÞÝ²Þ Û
°°±±²²Üßܲ²±
ÞÝ° Þݱ±ÝÞÞÝÝ
²ÞÞÝÝÛ²Ý 
±²²±
۰ݱÝÞÛÞ°
°ÞÝÛÞÞÝÛÝ
ÝÝ°ÞÝÞÝ °°±±²²°°°²
²±ÝÝÛÞ 
ݲޱÛÝÛÝ
ݲÞÞÝÞÛÛ²
Þ±²²
°°Ý±ÝÝÛÞ
°°ÞÝÛÞÞÝ
ÛÝ°ÞÞÝÛ ÛÞ
°°±±²²°°°²²±ÞÝ Ü Ý
ÝÛÞ °ÞÝ
ݲÝÛÞÞÝÝ
ݲÞÛÛ²±°±²
Û°Þ°ÞÝÛÞ
°°ÝÝÝÛÞÛ
ÞÛÞÝÝ°ÞÝÞÝ°±±²²°
°°²²±Ý²±Ý Þ
Ý Þ²ÞÝÛÝ 
°Þݱ²ÞÝÛÞ
ÝݲÞÛÛÛ²ÝÞ
±²
ßÜÝ°ÝßÞ ßÛßÜÝÛ
ÞÛÝÛÞ°ÜÛÝÛ ß
Üß±²²°°°²²±²±
²Ý ±°ÞÝ°°ÝÛ
Þ²ÞÞÛÞÝÝÛÞ
ÝÛÛÛÛ²°±
Þ ß ÞßÜ ßÞÝÛÞßÝÛÝ
°ÛÛ ÝÞÜß
ܲ°°°²Û²Ý Þ
Ý Þ²±²ÞÝ
°°ÝÛÞÝÝÝÝ
²ÞÞÝÞÝÛÛÛÛÛÝÞ
°
ÜÜ Ý ßÞÛ ÞÞÞÝ
ßÞ °°Ý±²²²°°°²
ÛÛ ß ± ²Ý Þ±²
ÞÝ°°Ýݲ²ÞÛ
ÝÛßÞÞÝÛÛÛÛÛÛÞ
±
° ßÛÛÜÜÜ ÞÝ Û Û °°±±Þ
²²²°°°²ÛÛÝ ± Þ
±±Üݱ±²Þ
Þ°°Ý±²²ÝÞÞݲ
ÝÞÝÛÞ²²²²²Û²
° Ü ßßÛÛÛÛÛÞÝÜ Û Þ ßß
°°°°°°°°²ÛÛÛÛÜ ßß Ü±
²Ý±²ÛÝ°°Ý±±±±Þ±ÞݱÝ
±ÝÛÞ±±±±±²²
± ßßß ²Ý ÞÝ ÝßßßÛÛ
ÛÛßÞÝ Ü±²²ÝÞ²Û °
ÞÞ°°°°ÝÛÞ
°°°ÝÛÞ°°°°°±±
ÝßßÜÜ Û ÞÝ Þ ß ÜÜ
Ü ß ßþ²Ý±Ý
±°°°°°Ý°°ß°
ßÞÝ°°ß°°Þ
ÞßßÜ ß°°
² ÞÝßßßÜÜÜß 
ß ÜÜܲ °±ß±±±±
Û ß ß ÝÛÞß Üß Þ ß
 ÜßßÜ
Üß Û Û ßÜÜ
±ÛÛ°ÜÝ °° Ûß
ÞÝÞ
²²ß ܱ°² ÛßÝÝ Þ
ÞÛÝ°ßÜÝÛ ÜÜÜÜÜÜ
ßÜÜÜÜÜÜÜ
Ûܲ±°ÞÝ° Þݲ
ÞÛßÜ°ßÜÜ ß Ü 
ßßÛÛÝÞßßß Ýßß
²±°°ÞÝ Ý±ÛÛÛ²
ßÜܲ²Ü Ü ßß Ýßß 
 °° Þ
ß°°° ± ÞÜÞ°
Û²ÛÛÛßÞÛÜÞÜÜÜ
ÜÜÜܲ±° °±±°Ý °±
°±±° °ÝÞݲ
Þ²²²ÛÜÛ²²Þ
Ü۲߰°°Û²²² Þ²Ü
Û²±° °±°Ý°±²
°±²²±°Þ±²±²Ü²²²²
ܲÛÛÛßÛÜÜ°°°°ÝÞÛ
°²Ûܱ° °Þ±±²°
±²²²±°°Þ°²±±±²²Û
²ÛÛÛÛÛÛÜßÛÛ²
ÜÜ°°ÞÛ²²Û±° ²±² 
°
ܲ°°²Þ²°²²ÛÛÜÛÛ
²²ÛÛÛÛÛ²²²±²²Û°Û²±²²
ݱ°±²Û°±
ÜÜÜÜÜܱ۱²Û
ßÜÛÛ²²ßßÛÛ²²²±±±°±²²²Ü
Û²Û°±°Þ°° 
°±
 °°±±²ÜÜ Ü °ß Ü
ÝÞ°Û²ÛÛÛÛ²ßÜÜÛÛÛÜÜ
ßß²²²±²²ÛÞ²ÛÛÛÝ° 
±° °±²
 ßßßÜÜ°±²Û°ÜÜß
²ÞÛÛ²ÛßÛÜß
±²ÛÛÛÛÛÛÛÜÛ²²ßÛÝ Þ
²ÛÛß° °° °±²
ßß Ü±±ßÜß°²²
Ý޲ݱÛÛ²±
²ÛÛÝ ÜÜß²²ÛÛÛ
Û²ÜßßÛܲÜÜÛß
±° Þ±°°±²Û
ÛßÜÛÛÛ°°±±Þ²°²²Üß
Þ°Û²±°±²ÛÝ ßß²
ßßß²Û۲ܲ ß
²²±° °±²ßܱ²Û
ÜÛÛÛÛÛ°°±Ý²²°²Û
²Ý°°°²ÞÛÛ
²±²ÛÛܲ±°ßßßßßß²±° °°°
²Ü°±²ÛÛ
ÛÛÛÛÛÛ°°±Þ²²°²Û
²°°±±±Þ±ßßßß ÜÜ
ßÛܲ±°Ü° ßÛÜÜÜÜÜÜÜ °°°°°
ÞÜÜܲ²ÛÛ
ÛÛÛÛÛ°°±±²²°²Û²Ý°±
±±±±° þ ßßß²ÛÜÜÛ
²±°±²ÝÝ°²±°°Ü 
°°ßßßßÛßßßßÛÛÛÜÜßß
ÛÛÛ
ÛÛÛÛÛ°°Ý±²²°²Û
²°±±²²²± ° °±Üß²°ÛÜÜ
 Þ²ÛÛÛßßßßÛ 
°²±°ÛÛÛ ÛÛÝÞÛÜÜßßÜܱ±
ßßÛÛÛÛÛ
ÛÛÛÛ°°±Ü²²°²Û²
Ý°±²²²²²±°²±²±
Û²ÝÞ Þ²ÛÛ²ÜÜßßÝÞ
°Û²±ÛÛÛÝÞßÜÛÛÛÛÝÞ Üß
±²°±²ÛÛ
ÛÛÛÛ°°±±²²°²Û²ÜÜ 
ßßß²±°²±°²ß Ü 
Ü²Ü ßßݲ±°°°°²ÛÛÛßÜ Û
ÛÛÛÛÛ ÛÛÛÛ°²Üß²°²Û
ÛÛß ß±±²²°²Û²Ý
²±ݱ²ÛÞÜÜ ÜÜß²±ÜÜܲ
Û²ßß²²²±° °°ÛÛÛÛßÛÝÞÛÛÛ
ÛÛÛÞÛÛÛÛÛ°²²²²±²
ÜÜ ß°±±²²°²Û²
±°Û²ÛÛ²ÛÛÞÛÛÝÛÝÜÛÛÛÜÜÜÜÜ
ßÜÜÜÜ Þ
°°ÛÛÛÛÛÛ ÛßÛÛÛÛÝÛÛÛÛÛÛ°²²
²²±²
ÛÛ°°ÜÜݲ°²Û
²ÝÞÞÛÛÞÛÛÛÛÛÛÛÛÞÛÛÛÛÛÛ°±
ݱ²Ý²ÛݱÞÞ± 
°°°ÛÛÛÛÛ ÛÛÝÞÛÛÛÛÛÛÛÛÛÛ°±²
²°²Û
ßÛ°°±±²²°²Û²²
ÝÞÛÝÛÛÞÛÛßÛÛÛÛ° ÛÛ°±²Ý±²²ÛÛ²Ý
Ý²Ý °°ÛÛÛÛÛ ÛÛ Û 
 ÛÛÛÛÛÛÛÛ°±±±²°²Û
Ü ß±±Þ²°²Û²
ÝÞÜ ßßÛ ÛÝÞÛÝÛÛÝ°± Û°±²Û
ݱ²ßÛÛÞÞÞ± 
Þ°°ÛÛÛÛ ÛßßÛ ÝÞ°
ÛÛÛÛÛÛÛ°±±±±°²Ý°
Û°°Ü ²²°²Û
²±°Þ²Û ÛÜÛ ßÛ ÛÛ ²ÝÛ
 °±²Þ²Ý²ÛÝß ß 
°°°ÛÛÛ ÛÛÛÛÛ ÝÞßÜßÛÛÛÛÛ
°±±±°²ÛÞ
°°±Ý²°²Û²ÝÞ
±ݲÛÝÞÛÛÝÞÛÛÝÜÛÝÜßÜßßßÜÜ 
ÜÜ ÜÞÞ± °°ÛÛÝ ÛÛÛÛ 
 °°ÝÞÛÛÛ°±±±±°²
Ý Ý
°ß±±²Ý°²Û²
²ÝÞÛÛ ÛÛÛÜÛÛÛÜÛÛÛÛÛÝÛÛÛÞ
°Ý²ÛÛÞ Ý²Ý Þ
°°ßÝ ÛÛÛÛÛÛ ß°
°°°Û ÛÛ°±±±°²Û
°Þ
Ý°±²²°ÝÛ²ÝÞÝ °²Ý
Þ²ÛÝÞÛÛÞÛÛÛÛ° ÛÛ°Û°±²²²
ÛÝÝÞÞ± °ßÜÝ ÛÛÛÛÛÛÛ 
 Ý °°ßßÛÛÛ°±±±
°²ÝÛ °
Þ±±²²°²Þ²± °±² ÛÛÝÛÛ
±Û°±Ý °± °±²Þ²
Û²Þß ß Ü°
Û ÛÛÛÛÛÛÛ ÛÝÞ °ÛÝÞÜÜÜßß
±°²ÛÛ
±±²²°²Û²Ý °°²ÜÜÜ ß ßÛ
ßÞ±²ß °Ýß°Ý ßß
Þ° ÛÛÛÛÛÛÛ ÛÛ  
ÝÞ Û ÛÛ°±±Ü°²
ÝÝ Û
²²²°²²Û²°°°±²²²²²±°°±ÜÜÜÜ
ÜÜÜܲ²±°° 
ÝÛÛÛÛÛÛÛ ÛÛÝÞÛÝÞÛÛÝÞ°±±±°²Û
Ý
°°±²²Û²Ý °°°±²²²²²±±°±²
°±²²±°±²²±° 
° ÞÛÛÛÛÛÛ ÛÛÛ ÛÛÝÞ°°
ܱ±±±°²ÝÝ Ý Ý
ßß²²ÛÛß°°±±±±±±°±Û
±²²±²±°° Þßß 
ÛÛÛßÜÛÛÛÛÝÞÛ°ÝÞÝÞ±±±
±±°²ÛÛ ÞÝÞ
ÜÜÜ°Û±²²±°° °° 
° ÛÜÜßÜÛÛ °°Ý
°°±±±±±±²°²ÛÝÜ Û Û
ßßßßßßß ±° ß ÝÞ
°°°°°°±Þ±±Ýß Þ
±²²²°²ÛÝ ÞÝÞÝÞÝ
ÜÜßßß°±²²±° ßßß ßß
°°°±±±²²Üܲ²²²²°²Ûß 
° Û Ý Û
ÜÜÜÜ ßÛ²±° °±ܱݲ±° °±ß Û
 ÜÜ ° Ü ßßßßßßß Ý° ÞÝ Þ
²²ÛÜÜÜ°±²²ÛÛÜÜܲ²Ü²±°±
Þ²²²±°°±ßÝ°ÞÝ Þ²Ý° Üß 
Þ²Ý ² ÛÝ Û ± Û Þ
ßßßßÜÜ°±²ß²²ÛÛÛ²Ü
²±±Þ²Ý²±°
Û °ÞÝ ²²Üß ²±
± ÞÝ Þ ° ÞÝ Ý
²ßÜÜßÜ°±ß²Û
²Û²²Ü²Û² ܱ
Û° ÞÝ ²±° Ý Û²
Ý Û ÞÝ Ý ²Þ
ßßÜܲ޲Û
±²²²²²ÜÛ²°ÞÝ° Û
 Üß޲ݰ Û Þ²Û ²
° Ý Þ ÞÝ
ßܲ޲²Û²±±±±±²²
Ý°ÞÝÞ Û ° Þ²ݱ ÞÝ ÞÝ Û ÞÝ ± Þ 
²
ÝÞÝݲ޲۲±°°°°
ßÜÛ °Û Þ Û Ü ° ²ݱ ÞÝ ²
Ý°ÞÝ ÞÝ ² Ý Ý ²
ÞÝ ÛÜܲ²Û²±ßßß 
۲ݰ Û Ý Û ÞÝ° ²Ý °ÞÝ 
Û°ÞÛ° ²± Þ Ý°ÞÝ
Û ÞÜÜÜÜÜÜÛÛÛÛ
²Û ÜÜßÞÝ Û²ß ° Ý Ý Û Û °ÞÝ 
°ÞÝ ÛÛ ²° Þ Þ°ÞÝ
Û Ý°²±±²ÛÛÛ²²²Ý 
²²ß ß Û²ßÞÝ Þ ÞÝ Þ Û
 ÞÝÛ Û ÛÝÞ ÛÝ ²Ý° ÞÝ Ý Û
ÜÜ ÞÝ°²°±±²ÛÛ²²±
Ý ±²ß Üß Û²
Û °Ý Ý ÞÝ ÞÝ Ý²Û Û ÞÝÞ ÛÝ ÞÝÞ ÞÝ Ý Û
ßßÜ°²°±±²ÛÛ²²±Ý 
°ÛßÜß Ü²ß Ý Û° Ý ÝÛ ÞÝ 
 Û° ÝÛ Þ ÞÝÞÝ Þ Þ ÞÝ °Þ
Þ ßÜ°²°±±²ÛÛ²²±
Ý ßÜßÜÝ Ü²ß Û ÞÝ°ÞÝÝ Þ Þ
Ý Û Û ° ÞÝÝ°ÞÝÞÛ Þ Þ Û Þ Þ
Üß ßÜ °²°±±²ÛÛ²²±
ßÜßÜßÜ°Ûß Ý Û °Û °
ÞÝÞ Þ Û Û ÞÝÞÝ° Û ±ÞÝ Û Þ Û Û °Ý
ÜßÝ °²°±±²ÛÛ²²ßÜ
°Û °ßÜß Û Þݱ Ý
± ÞÝ Ý Û Þ Þ °Û ° Û ² Û ÞÝ °Û Þ °Ý°
Þ °²°±±²ÛÛ²²±±ß
ÜßÜßÜßÜ°Û Û ² ° Û
²ÝÞ ÞÝ Ý ± ß °Þݱ Ý Û °ÛÝ Þ °
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
ÛÛÛÛÛ Prophet is Copyright of Rob 
Liefeld - Image ComicsÛÛÛÛÛÛÛÛÛÛÛÛ 
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
ßßßßßßßßßßßßßßßßßßßßßßßß
ÝÜß
ÜÜÜßßÜ
ßßßܱ°±ÜÜÜ
ßßßßßßßÜÜ 
ÞÝ
²±°°±²²±° °²±°°±²
²±°°±²²±°²±°°±²²±
°²±°°±²²±°Ü
°°°Ü ܲ²ÛÜ ß ²±°
°±²²±°
ßßßßßßßßßß ßßßßßßßßß
 ±²²²²±ßßß
ßßßßßßÜßßßßßßßßß ß
°±±²²²²²Û ßßßßßßßß
ß
ܱܰ±²Ü±Ü 
²²±Ü ±²²
ßܱÜß±²²Ü°
°±²ß±²²ß±²²
ܱÜ
ß±²²±Ü±²²±
Ü°±²±ß ²±°
²±°±²ß±²²
±Üß±±²±²²
²Üß °±²ß
±²²±Ü
ß±°°°Ü ²²±°°°°
ß ±°°°Üß 
°°±ß ß±°°°
Üß±²²±°Ü
ßßÜ°°±ß±°°
°Ü
ß°±²²Û²±°ß°±±±
Ü ÜÜß°±±²²±°°
Û²²±±°°°ÝÞ°Ü
ß°°±²Û ²Ü Û
²²±±°°°Û²²±±°°°Ý
ßßßß ßßß ß±²²²Üß
°ÜßßßßßßßÜßßßß
ßßßßÜÛÛ°°Üßßßß
Ü°±²Üßßßßßßßß ßß
ßßßßßß
Üß²Û²ßܲ²±±°°ÛÛÛÛÛÛÛÛ
°ÛÛÛÛÛÛÛ°°±±²²Ü°°±²Ü
ܲ±°Üßܲ²±±°°ÛÛÛÛÛÛÛÛÛ
°±°ÛÛÛßßÛÛÛ°°±±²²Ü°°±²
Ü
ÜÜÛÛÛÜÜ ß²±°Ü²²±±°°ÛÛÛÛÛ
ÛÛÛÛ°°±±²±±ßÜÛÛÜßÛÛÛ
°°±±²²Ü°°±²Ü
Þ²²ßßßß²²²Üß²²
±±°°ÛÛÛÛÛÛÛÛÛ°°±±²²ÛßÜ
²²²²²ÝÞÛÛÛÛÛ°°±±²Ü°°±²
ÜܲÜ
±±Ý Üß±ßܲ²±±°°
ÛÛÛÛÛÛÛÛÛÛ°°±±²±Üß ±±±
ÛÛÛÛ°°±±²²ß°±²²ßÞ
±±±Ý
°°Ýßܲ±°ß²²±±°°
ÛÛÛÛÛÛÛÛÛÛ°°±°°Û °°°
ÛÛ°°±±²²ß°±²²ß
°°°
Þ ßß²±°ß²²±
±°ßßßÛÛÛÛÛÛÛÛ°ÛÛÛ  
°°±±²²ß°±²²ßÞ
 
°°°°°°°°°°°Üß²±°ßß
ÜÜ°°°ÜßÛÛÛÛßßÛÛÛÛÝÞ
°°±±²²ßßßÜÜÜÞ
°Ý
ßßßßßßß±±±Ý ßßßÜ
±±ßßÜß±±ßßÜ
±±ÜßÛÛÝÞ±ÝÞ
²²ßßܱ±±ß
±±Ü ÜÜܱÝ
Þ²²²²²Ü ß ßßß ²
ÝÞß²²ßÜß²
°ÝÞ²ÝÞß°
Üß²ß ßÝÞ²²ßß
²²Ý ÜÜÜ ²Ý
²²²ß²²Ü²ßßÞ
²ÝÜÝÞ²ÞÝÞÝÞÝ
Þ²ÝÞ±²²ß Ü 
ܲ²Ü ²Ý Þ²Ü
²²ß ß²Ý
Üܱ±±Ý Þ±Ý 
ܲ±±ÝÞ
±ÝÞ ±±±±±Ü ß Ü
ÜÜܱ±±±±Ý±Ý Þݱ
±±±Ý
° °±²Û°°°°°°°°°°ÜÜ°°
ÜÜÜÜÜ °°ÜÜß ÝÞ
°°ÝÞ°°°°°°°°°ßßßßßßß 
°°°°°°ÜÜ Ü Þ°
ÜÛÛÛÛßß ßß ßÜ ßÜß
²±ÜßßÞÝßßßßÜÜÜßß ÞÛÛÝ ßÜßß
ßßß ßßÜ
 °Ýß²²±°ß°±²
²ßßß
°°ß²²±²²ß
±°ß²ß
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄı±ÜÄÄÄÄÄ Cru
sty's SpamLan
d ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄSysOpsú WarlockÄÄÄIJ²
ßÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ914.9
44.8046ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄDeadpool [GRF]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄ96oo - 14.4 only
ÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄGRF Affiliate BoardÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[24oo by 
invite]ÄÄÄÄÄÄÄ
ÄÄArt, Music, & Anarchy ONLY!
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄRunning Obli
vion/2 Registered
ÄÄAll Artists, Coders, & M
usicians welcomeÄÄÄÄÄÄÄÄImpac
TNeT, ToXiCNeTÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ!ÄIcy of 
ACiD Producti
onsÄ!ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Greets to all ex-Valiant guys!7.28.93

19
mods/art/MATRIX1.ANS Normal file
View File

@ -0,0 +1,19 @@
 ーーーーーーーーーワイワワ  ー  ワワ 
 ーーーーーー ワワ゚ロロロイロロロロロ゚  ーー  ーーー ーーーー ー ワワワ゚゚゚ワワイロロロロロ゚
ーワワワ゚゚゙ロロロロイイロン ーー  ワワワ ワワ ーワワワ゚゚ロイイロロン
゚ワワワロロロイロ  ーロロロイイイアアワワワ゚゚ロロロロイロ゚ロイイイイアワワワイイイイーー ーー゙ロロロロロイ
 ゙ロイイロロロン゙ロイイアアアーン イアワワーア゚ ゙イイイイロン ゙イイアアアアアイイイアアア゙イイロロロン
ロロロロイイ゚     イイアアーーーロロー ーーーーン  アアアイイ イイアアーー ーアアアーーーーアアイイロン  
ーーイロイイアーーーー ー  ゚゚゚ーーロロヷーーーーアアーー ーー ーー ーーアア ゙ ーアーーーー゙ ーーーーーーー ーー ー ーーーーーアアイーー   ー゙イアアーー ワワ    ーーアアイロ  ゙アアーーー  ーーーアア ゙ーーーーアン ワ ゙ロ ーーアア 
ワ ゙アーー ーーン  ワ ワロロワワワ ワロイイイロロン゙ワイ゚ ゙ロイイアーー ーーアアアア ワ アアアアイロ ゙ロワロロイロ ゙ロロロロー  ゙ワ 
ーン ー ーーアイン ーーロワ ロロイイロロロロロロイロロイン ーー ゚゚゚゚ロイアア゚゙アアイイ ゙ーン ロイイロロン ローーロロン ーーーーロロン ロロー
゚  ーーーアアイイ ゚゚イ゚ ゙ロロロロロロイロロロロロロイ ゚゚゚イ ゚゚ イイロン ゚イ゚ ゙ロイロイイ ワワワ ゚ ゙アアーーーン ゚イ゚
゙アアアイイロン  ロロロロロロロロロロロロロロ゚゚ロロイロ゚゚ ゚゚゚゚゚ ロイイアアアア
ロイイロロロロ ゙ロロロロロイロ ロ゚゚ ゙イワロロイイイロン
 ワワ゚゚ ゚゚゚ワワワ ロロロロイ゚ ワワロロロロ゙ロロイロロ 
 ーー ゚゚゚゚゚ーーー ーー enigmaォbbs softロロロイイロンー ゙ロロロロイ ーー
dangermouse ーーロイロロロロロイロイロ ー
  ーー  ロイロロロロワワワワ゚゚゚゚゚゚゚゚ワワワ
゙ロロ゚゚ーーーーー
 ー ゚ ーーーーーーーーーー


823
mods/art/SO-CC1.ANS Normal file
View File

@ -0,0 +1,823 @@
ܲ±ßܲ±° ° Ü °°±°±±²
²±²²Û²²±²±°±°° °Û °ÛÛÛÛÛÛÛÛ
ÜßßßßßßßßÜßß Üßܲ² Üßß² ß
°ÜÜß°²° ° ÜÜß ° °°°°°±²²Û²²
Û²ÛÛ²²ÜßßßßßßßßßÜÜܲÜÜ ÜÜ ²
ßßß ßß ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ Ü°°°Û
°ÜÜ°ßÜÛÛ° Û
° °Ü±²²ß ßß ßÜ ÜÜ Ü²ß ßßß ²ßÜÜÜÜÜÜÜÜÜÜÜ
ßÛÛÛÛÛ Ý ÜÜÜÜÜÜÜ Þ °Û
°ÛÛÛÜßßß ßßßßß Ü²Ü
Ü Ü²ß ßßß ÜÜÜÜÜÛ²²±²±°±° ° Û ÛÛÛÛÛÛÛÛÛ
°°Ý ÜÛÛÛßß ßþ Þ ±Üßß
ÜÜ ²Ûܲ²ßß ß ÜÜÜÜÜÜ°°±±°±²±²Û²²
²Û²²Û²±²±°° °Û Û ÛÛÛ
°ÛÛÛÛ ÝÞÛÛÛÜÞ °ܲÜß ßÜÜÜ
ÜßßÛÛÛÛÛ°ÛÛ°°±±±²±±±²
Û²²Û²±ßßßß²±°±°°±° ° Üßß²ßßßß Ý 
ßÛÛÛÛÛÛÛÛÜÜÜ Þ ÛßÜÜßÛÛÛÛÛÛÛÛÛ
 ÛÛ° °°±°°±±±±±²²²Û²ß 
Ü°°°Ü ßß²ß Ü ÜÜÜ ÜܲÜÜ Ý ßßßßß
ÜÛÛÛÝÞ ÜÛÛÛÛÛÛÛÛ°ÛÛ Û
°Û Û Û°°±±±²±²²
ßßß² ±°±Ü±°Ý ß ßßß²ß ß ÜÜÜÜÜ
ÜÜ ÝÜÜÛÛÛßß Þ ÜÛ°ÛÛ°° 
ÛÛÛ ÛÛÛÛ ÛÛÛÛ°°±²
ß þ ßßÜÜ ±°±²²²±ݲ ܲ۲±
±±°±°°°°°Û° Ý ÜÜÛÛßßßÞ 
°°±°ÛÛÛÛÛÛÛ°Û °ÜÜßß
ßß ß ß±²Û²²ÝÞ°±
²±±±±²Þ ²Û²²²±²±°±°±°°°°°
Ý Ûßß ÜÜ ß þ Þ Û °ÛÛÛ
Üßßß²ß ß° ÜܲÜÜܱ
°Ü ÜÜÜß² °°°±°°±±±Þ 
Þ²ÛÛ²²²²±±±°°±°°°ÝÞÝ ÜÛß ßÜ Þ ß
ÜßßÜܲßß Üܲ Ü°±²Û²ÛÛ²²±°
Üß°ßÜ Þ±°°°°±°±ÞÝ 
ß °ß ß ßßßßß ÝÞ ÛÛÞÝ ÞÜß ÜÜÜ
ß±²Û² °°±²²²±ß°ßß²±°ÝÞ
°ÝÝÞ°°°°Üß°±
ÞÝ Ü²Ü Ü²Ü þ Ü Ý ÞÛÝÛÛ ÞÜ
ßÛ°Û°±²Û²
°°±±±ßßßßßßß°²±° Þ
°Ü°ß°°±²Þ
°²Ý Þ²Üß²²Üß²²ÛÜ ßÜÜ Ý ÛÛÛÜÜ Ü
ÜÛÛÝ Þ ß°Û°±°°±²²
°°±°±°Ü°±±°°Ü°ß±°
Þݲݱܰ°±ÝÞݲ  °
 ÜÜß°Üß²°°°
Üß Ý ßÛÛÛÛÛÛÛÛß Þ ²°
°±°±²²ÛÞ°°°±°°±²±°ßß
°°ß°ÝßÜßÞ°±²±ÝÞ²ÞÝ
Û °±°° °ÛÜßß± ßß°² Ý
ßßßßÞ Ü°±²±²Û²Ý° 
°°±°Þ°±²±°±Ü ²Ýß²Ü Ü
°°±²ÝÞ Þ²±ÝÞ
°°±°°° °ÛÜ ±Ü Ýßßßßßßßßßßßßßßß 
±±²Û²ÛÛß Ü °°
ÞÝ°°±±°Üß²ß Üß ÜÜ
 °°°Þ²° ݲ °Ý 
°°°±±°°°Û² ß Ý S™-CC1.ANS Þ
²Ûßß Ü Þ² ±Ý°
²°Þ±°Ý ²ßÜÜ
 ° °° °ÛßÞ²Þ
° °Ý ßÜß° °±±ß Ü ° 
ßßßßßßßßßßßßßßßß °ß ܲ
°Ý ²ß °Ý°Ý
°Ý°°°Þ °Þ
 °°° °°°°ÝÞ²°ÜÝ °°Ý± 
± ²Üß°ß Üܲ±°
°ܲ ß þ °ß±
ÜÜßßÜÜ°ÝÞ
Û°° ß ß ÜÞ° 
ÞÝÞÝ°Ý  Ü°°°
°°°°°°° ßßÜ°Þ
°°  ÝÞ²°ß² 
Ü °±±ßÞܱ²Ü°
ÞßÜ°ßÜ  ÜÛ°
Û°±Ý
°Üß Ü  ²ÝÞÝ ß
  °Þ Þ 
 °°°°°°°°°°° ÝÞ°°°°°°
ÝÞ ß ° ² ß
°ßß  ܲ²²²²
Ý ° Üß°
Ý°Û°Û°°°±
 Ü°°ÜÝÞÛÝÞ  Ü
  Þ ° °°°°°°°°°°°
ÝÞÝÞ°°°°°Û² Ý
 Ü ß  ßÞ
²±²²²² Ü þß°
°Üß°Û°°°
°±±ß² °Û Ý°Ü
 °Ý  Ý °°°°°
°°°°°°   °°°°Ûß
 Þß     ±. Ü
±²±²±² °Ý°°
Ü ß²ÜÛÛ°Û
ßÜÜß °±Ý°± °°°
 Þ°Þ °°°°°°°°°°°Ü
°ÝÞ°°°ß °Ü
Ü±Ü  Þ°°±°±±²
ÝÞ Þ±Ý
Þ²ÜܲÜÛ°
ß Ü°±ß°² °°°°
ÝÞÝÞ °°°°°°°°°°°°° °°
²  °Ü²  .þß²
Þ°ÛÝ  °°°±²±
Ý Ü±²  °ßÛ
°Û°Üß
ÜÛ °ß þÞ °°°°Ý
 °  °°°°°°°°°°°° °±
²  Ü°ß ÜÝ
Ü ÜÜ  ±ß
 ÜܲÜÜßß°±°°Þ±ß
 ²°Ü ß°±°
Ý
°ß  Üß°Û
 °°°°°  °ÝÞ°°°°°
°°°°ÜÜÜÛÛ²°  °Ý Þ
°²ÜÜ ßÜß
²ÛÛ²±° ÜÜßß±²
Ý ß °±°  °±±
 S™ß °Ü 
Û°ßß ß
ß ²ß  
ßßÜÜÛÛÛÛÛÛÛÛÛ Þ
°±Ý ±°±²Ûß
 ÜÛ²  ²ÛÛ
²±° ° °±ÜßþÜ 
 °±±  °±
 °Ü ßß° ÜÜ²Ü  
ܲÜ  ÜÜ° ß
²ÛÛÛÛÛÛÛÛݲ±²± ßßß
ÜÜÛÝÞÛÛÛÜ ßÛ²²±°° °°°
 ß°Üß °°°±±
 Üß
°²ßÜܲ°ܲßß ß 
     ß°
²Ü ²ÛÛÛÛÛÛÛ²²±±²ÝܲßÛÛÛÛ
 ÛÛÛÛÜ ßÛ²±±°°°±
ÝÝ  Ü ² °
°±ÝÞÝ
± °Üß   
ß² .þß   Ü ß
°² ²ÛÛÛÛÛÛÜ
²±²²ÜÛÛÛÛÛÛÛÝÞÛÛÛÛ²Üß
²²±°°±± ² °Þ
 ßܲ °ÛÛ °
ß°² ܱÜ °
 ܲÜßÜÜ ܲßܱ
Üß  ß°Ü
²ÛÛÛÛÛÛ²²²Û²ÛÛÛÛÛÛ
ÛÛÜÛÛÛÛÛÛ²Üß±°±±² ±
 ² ܲ±°Þ°Û
°
±° ²° °Ü 
 ßß±ÜÜÜÜÛ²
ßß Üܲܰ°±²ÛÛÛÛÛÛ²²²
ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ²±Ü°±²²
 ± Ý ²Ûܱ ÛÛ Þ
Þ²° ²°°±°°ÜÜÜ
 ÜÜÜÜÜÛÛÛÛÛÛ²°°±²ÛÛÛÛ
ÛÛ²²²²ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ²±°°±²Ý
ܱ² Ý°±²Û² ÞÛÝÞ
Üß²°°ß±±°°°°°°±Ü²ÛÛ
ÛÛÛÛÛÛÛÛÛ²°°²ÛÛÛÛÛÛÛ²²²²²Û²ÛÛ
ÛÛÛÛÛÛÛÛ²²±°±±²Ý ß.
± ²Û² ²ÝÞ
ßßÜß²Ü ²±°°°°±±²
ÛÛÛÛÛÛÛÛÛÛÛÛÛ²°±²ÛÛÛÛÛÛÛÛ²±²²²²ÛÛ
ÛÛÛÛÛÛÛ²²±±±²² ÝþÜ
² ÜÝß ²
²ÝÞ
²Ü ß þ°Üß±°°°°°±²
ÛÛÛÛÛÛÛÛÛÛÛÛÛ±°±²ÛÛÛÛÛÛ²
Û²°±²ÛÛÛÛÛÛÛÛÛÛ²±±±²²Ý
ßÜ°±²ÛÛÜß±Ý
°
Û²² Ü  ß ß±°±°°±±²²ÛÛÛÛÛÛ
ÛÛÛÛ²°°ÝßÛÛÛßßßß
°°ßÜÛÛÛÛÛÛÛÛÛÛ²±±ÜÜ
ßß°²ÛÛܲÛܲ°
ÜÜ  ±
Û²ÞݲÝ Ü°  ß²±±°°±±Û²Û
ÛÛÛÛÛÛÛÛ²±±ßß°°°Ü
°ÜÛÛÛÛÛÛÛÛÛÛÛÛÛ²²±±²ÛÛ 
ÞßÛÜßßÜ°ßß
 ÜÛݲ
Û ²ÝÛ ² ݱ²Ü ß²±±°°
±±²Û²ÛÛÛÛÛÛÛ²²Ý Ü
±°²ÛÛÛÛÛßßßß  ÜÛ²±²±²
ÛÝ Ü  ²²±°ßßÜ
߲ݰݲ
ÛÝÛÞݲ°ÝÝ°±²ÛÜ
ß²±±°°±±±²Û²ÛÛÛÛÛ²±Ü
°±²±ßßßÜÜÜ²ß ° ÞÛ
²²±±²ÛÛ ß²Ýß  Þ
°  ÜßÝ°Ý
±
°ÛÜß Üß .
²ßß²Û   ß²±±°±°±²±²²Û
²±°ßß߱ܲ۰۲ßÜ
±°ܱ° Û²Û²±²²ÛÝÜ
 Þ ܲ Û ²
 Þ°Ý° ±
ÛÛ°°Ü ²Ü²
Üß ²Ûݲ° ß²±±±°±°±±²
Ü  °ßß ÜÜÜܱßÜ
²ßÜ°² Û²²²²²²Û
ßÞ°Ý ² 
ÝÞݳް ޲ݲ
°
Û°ßßܱßÛßÛÝ
Üß ² Þ±²  ß²²±°°°±
°° ß °²ÜÜßßßßÜ
ܲß²ßÜÜÛÛ²±²
Ûß ° ±² Þß°° 
  ° ݲ ÝÞ°
Ü ßß°ß±²Ûß±²ß
ß ÜÞ²Ý ±  ß²±±°° °
Ü ßßß ßßßßß
ÜÜÜÛÛ²Û²²Ûß
  Û°²²Ý °±° 
Ý°Ý ²± Þ±
ÛÛÜ ܲÜÜܱßÜ þß² Û
 ² ßß
Ü° °° °ÜÜÜÜ
ÜÜÜÛÛÛÛÛÛ²Ûß 
Ý°±²ÛÛ °²
°±° °±²  Þ°
ÞÛÝÜ°Þ²Þ²ÝÜ° ²°ÜÝÞ²Þ
°  °° ßß °±²
Û²ÛÛÛÛÛÛÛÛ²²ß ß
 °²Û²ÛÛ °²±°
Ý °°± °±
²ÛÛÛÜßÜ ° °°
²²ÝÞ° ±²  
°   °°  ßß
 °±±²±²²²Û²ßß  ß
 °±²ÛÛÛÛÛ ²Û
°±°²
ÞÛÛ°ÛÛ² ÝÞ°°°²
² ±± ²Ý Ý
   ° °°° ßßßß 
  ß °°²ÛÛÛÛÛÛÛ
²  °  ² °±
 ÝÛÛ ÛÛ  °°±°°²ÝÞ
ݲ ß ²  °±
° ° Þ °°
²ÛÛÛÛÛÛÛÛÝ  °
ܲÝÞ±°
ÞßÛ° ÛÝÞ²°°°°°²ÜßÞ²±Ü
 ±  ± ° ° °
  ° ±²²ÛÛÛÛßß Ü°
ß²²  ° 
²ßÛ°Ûݲ±°°±°±°°ÛÞÛ ²ÛÜ
 ° ²°°° ° 
Û °±²ßßß ÜÜÜ
ßܲ°Ü  ßß²
Þ°Üß°° °²°±±°±
°°Ý°Û ²ÛÛÜ ÞÝ
   °°  °
 ²ßß Ü þÜ
ßÜÜß²°±ßÜ²ß ²Ý
²Ü
 ²°Üß±°ݲ°°±±±
±°Ý°°Û °²
Û°Üß   ° ° °
     ÜÜß
±ßÜܱܲ°ßß²Ü
 °ß ÜÝß  
±²
 ²°± ±° ²°°±
°±±Ý°°°° °
ÛÛ°°Ü  ° 
  Ü°Ü °
Ü°±Ü²°°ß°±ß߲߲
ܱܲ߰ÛÜß
 ÜÛÛ² ÞÝ  °
  ß²° ÛÛ ²°°±±±±
Þ°±°°Üß°Û
°°Û  °ß±°
²°±² ß²Ü Ü²ÜßÜ°ß±
²ß²ßßßß Ü Û
ÛÛ²² ÝÞÛ
 ÜÞ
ßÛ² Ü°°ß
°ÜßÛÜß°°±±±Þ±°
±°°°Ü° °°Û  
  ß ßß  ß ß
 þ Ü Ü ÜÜÜÛß
°ÝÞ²Û²±  ²
 ° ÝÞ
°° ² ²ß°°ÜÛÜß
°°±°Þ°±±±°±°±°°±°°
° °  °²Ü²Ý²ÛÞÜÛÜÛÛÜÛÛÛÛÛ
Û²ÛÛÛ² ²±²± ° 
Ý Ü ²S™
 ° ° ² Üß±°Ü Û Û
°°Ý°±²±±±±²±°±±°Ý
 °±²±²±²² ÞÛÝÛÛÛÛÛ²ÛÛ
ÛÛÛÛÛÛÛÛÜÜ °°
Ûß° Þ± Þ
Ý
°ßß² °Ü² Üß±²Ý 
ÛÜ߰ݱ°±±²±²²²±²±²±
  ²Û²Û²²Û ²Û ÛÛ
²ÛÛÛÛÛÛÛÛÛßßßßß
°²Þ Üܱ²ÝÞ
° þ Þ
°°²ßÜÜßÜ Þ²ß±²° ÛÛÜÝ
°°°±±Üß²²²±±±°Ý 
 ²ßß²Û²ÝÛÛ Û²Û²ßß°Ü°°
ÜÜÜ°±°±Üß ÞÛ±±²
 ßÝ ßÜÞ
ÜÛÛ²ÛÛ² Ü Þ
°Ü±±°ÛÛÛÝÜß°°
±±²²²±±±±±ÝÞ²
²²ÜÜÛÝÞÛݲÛ² °Ü
±°°±²±²²²±²± ÜÞ²±²
ÝÞ² ß² Ý
ÛÛÛÛÛ² ²²° ²
°°±°°ÛÛÝÛÛ Û°°±±Þ
±±±±±° ²²Üß²ÛÛ
 Þ²ÝÞ²Ý Þ±²±
²²Û²ÛÛÛ²Û Þ² ±°
± ±Ý
ÛÛÛÛÛ ²Û²Ý° ²Û°°°
ÛÛ ÛÛÛ ²ß°±Ý°±
ݱ±± Þ²ÛÜ ²
Ûݲ²ÛÞ±°Ü²²Û²ÛÛÛÛÛÛ
ÛÛ Üß ²Üß
Þ°  Þ  Ý
ÛÛÛÛÝÞÛ²Üß²  Üß°
ÛÛÛÞÛÛÛÛ ±²ßÝ°°±Þ±°
ÛÛÛÛ ß ÞÛÝÞ²±²Û²
ÛÛÛÛÛÛÛÛß°²ÜßÞÜßß ÜÝ
 Þ
ÛÛÛÝ Û° ²Û±°
ÞÝÞ ÛÝÞÛ°ÛÛ²Ü ²Þ
²°° ²Ý ÞÛÛÛÛ  
²ÛÛÞÛ²ÛÛÛÛÛÛÛÛÛÛ± °ßÜÜÛ²° °
ÝÞ ß²Ü  
ÛÛÛ ° Ý°Û²° Ü
 ² ÛÛ ÛÛÛÛÛÛ²Û ²ÝßÝ Þ
  ÞÛÛÛÛÝ ßÛÛ ÛÛÛÛÛÛÛÛÛÛß
°ÜÛÜÛÛß°± ²ßܲ ß 
Ý
ÛÛÝÞ±² Û²° ܲÝ
Þ°ÞÝÞßÛÛÛ°ÛÛÛÛ ²  
°ÛÛÛÛÛ ²ÞÛ ÛÛÛÛÛÛÛÛß ÜÛÛ
ÛÛß²°  þ ܲÝÞ °Ý
ÞÛ
ÛÛ ²²ß°²°
ßÛÛÝÞ±ß ÞÝÞÛ°°
ÛÛÛÛÝ°Ý  
ÛÛÛÛÛÝÛ Û ÛÛÛÛÛÛß ÜÛÛ
ÛßÜ ± ܲ ÞÛÛ²
Ý Þ ÛÛ
Û ±² ±°°
²ÛÛÛ ² ² °
ÛÞÛÛ °ÛÞÛ²ÞÛ ÛÛ²
ÛÛÝÛÝÛÝÛÛÛÛß ÜÛÛß² ß°þ
 Þß ÜÛß ÜÜÜ ÝÞÛÛ
ßÛ°ß±²° ²ÛÛ
ÛݱÜÛÝ °²ÛÛÛ°
Û°ÝÛ²Þ°ÞÛÛÛ
ÛÛÝÞÛ ²ÛÛß ÜÛßÜ ß þ
 Ü ² ÜÛÛÝ ßß²°°
Ü ÛÛ
²° ±° °±²²Û
Û Û°Û Þ°
ÝÛÛÛÞ°°ÛÞݲ°Ý
ÛÛ²Û²Û ÛÛÝ Üßܲß ±²Ý°
 ܱßßܲÛÛßÜ
°ÛÜÜ ßÝÞÛÛ
²° ° °ß²²²ßÜÛ
°° ÝÞÛ²ÞÛ°Þ
°°°ÝÝ°ÛÝ
ßÝßÛÛÛÝ²ß ß °ß Ü ß  ÜÜ
 ±²ÛÛÛÝÞÛÛ°Û°²
Ý ßÛÛ
ܲ°ß ²Û²²ßÜÛ
°± ² °ßÜÝ°Ý
°±°°Ý ÞÛ °
 °Ü ß Ü
Ü ßÜßÜÝܲ² ±
²ÛÛÛÛ² ßÜÜßÛßÜ ÞÛÛ
Þ²ß ²²ÛßÜÛ°°±
²Ý Ü°°ÝÛÞ±°
°°Û ÛÝ ° ²ÞÝß
²Ü ²Þ ß± þ þß
 ܱ²ÛÛÛÛÛß ß°ß
 þܲ ÛÛÛ
ß  ²ÛßÜÛ°°±ßÜ
²± Þ°°Û² ±±±°°°
 Þ ß²ß þ ° 
ß  þß  ܲ ±²²±²Û²ÛÛÛÛ
 ܲÛÜ ÝÞÛÛÛ
° ßÜÛ°°±ßÜ
²²± °ÛÛ² °±²±°°
° þÜß²°Ü
ÜÜÜþ²±ßßܲßܱ²ÜÛ²ÛÛÛÛ
ÛÛÛÝÞß Þß²Ý ÞÛÛÛ
Ü° °°ßßܱ²±° °
ÛÛ² Û±±±±±°Ý  °²ÜܲÜÜ
ßßß    °Üܱ²ÜÜÛÛÛÛÛÛÛÛÛÛ
ßßßß  ÛÛÛÛ
Û°°°ÜÜ°°±°±ß °
Û²ßÜ °²±±²±± °²Û±
ßß Üܲ±° ±²±ß±²°²ÛÛÛÛÛÛÛÛÛÛÛßÜ
°ßß± ÞÛÛÛÛ
°° ²ßßÜ°ß. 
° ßÜÛ °²²²±²²
 Üܲ²Û²Û² ޲۲ݲ۲ÛÛÛ
ÛÛÛÛÛÛÛÛÝÞݱ² ÞÜ °
ÞÛÛÛ²
°ßßÜßß Ü°  Ü°
ßÜ ÛÛ°²Û²±²²
°±Û²²²²²ÛÛÛ²ÞÝÛ²ÛÛÞÛ²ÛÛÛÛÛÛÛ²ÛÛÛÛ
 °²°²²Ü°
Ý ° Þ²Û²±
Ü°ß ܲ²° ÜÛßÜÛ
ÛÛ°²ÛÛ²²ß ÜÝ °±²
²²²Û²Û²ÛÛÝÛݲ²²ÝÞÛÛÛ²ÛÛ²ÛÛÛÛÛÛÛÝ
ÞÜÞ±²±±° ± ²±²±ß
ßÜÛß°ß° ߲ܰ
ßÜÛÛ°²Û²Ûß ܲß  ±²
Û²²Û²ÛÛÛÛÜ۲ݲ±²²ÞÛ²Û²Û²±²ÛÛÛßß
°ßÞ±²± Þ² 
±±± Ü
ß±°° ßÜÝÛ°°ßÜÛ°
±²ßßßܲ±ß ÜÜÜ
²Û²ÛÛÛÛ²Û²²±²Þ±²ÝÞ²Û²±²Û²ÛÛß
ܲß ß°Üß° ß
 ²Ý°±°ÝÞ²
ßÜ° ÝÞ°ÞÛ°
ݲÛßß Üܲ²±ß Ü Þ
°²ßß ²
ÛÛÛ²²±²±±²Ý°±±°²±²±²Û²ÛÛ  þ
Ü ÜÝ ÜÜ °ÞÝÞ
°°ÝÞÝ
ÜÜÜÜÜßß²ÜÜßÜÜÜ°±²²±ßÜÛ² þ
Üܲ²Ü ÛÛ²Û²²±°°°±°°± ±
²Û²ÛÛÛÛÝÞÝ °°ÛÜܲÝÞ
°Ý Ý Þ°°°
 Û
Üßß²ÝßßßÜÜÛÛ°°±±²±°°Ûß  
²Û°°ßÜß ßÛÛÛ²²
±°±° °° ²ÛßßßÜ ßÜ
°ßßß²Üß °° ±
°Þ°°°ÝÞ
°°Ü ²Þ°Û²ÛÛ
°°±²±±° ßÜþ Þß°±
ÝßÜ°ßÜ ÜÜ
ß²±°± ° Þß Ü ÜÝÞ² Ü ßßßß
ܱ°± ÞÝ °°±°°
Ý
° ² ²±°ÛÞÛ°°±°±°°
ßÜß²Ü߲߱
Þ² Ü°±ßÜß
 ÜÜ   Ü Ü
±° Þ² ÛÜÛÛÝ ²Û²±²±
±Ý °Ýݱ±°±°°
° Ý Ý°ÛÝÛÛ°±±°°
ßÜß ²ÛÛ²Üß
ß °Ü Üß
  ۲߲ ÞÝ
Þ±°Ýß °ÝÞÞÛÛ
Û Þ²²²²²±   Þ
Þ²±±±°±
 Û  Þ°ÛÞÛ°±±±°
 Û   Ûß°°°ßÜ°
ÞÝß°°Ý ÞÞ²
Ý° °Û°°°±Ü
 Ü ° ²ÛÛÝ 
ÛÛ²Û²²² Þݲޱ²±²±±
 °° °ÛÝÛÛ°°±°
 Û   °Ü² ±°°°°±°Ý
޲߰ Û Þ²
±°Ý ÞÞݲß²±°²Ý
 ß ßßÜÛÛÛÛÛ²ÛÝ
± ݲ²²²²²²
°°Ý °ÛÞÛ°±°±
 Û  °Ü²±Û °±°°±°±
± ß°ßÞþÛ
Ü Üß±° ß°ܲ
±²ßß ܲÜÜÛÛÛÛÛÛÛÛ²
Ý°ß° Û²²Û²²²
 °Ý ÞÝÛ°±±° ÛÝ
 ܲß°°Þ ±°±°±±±²Ý°
 ßßßß Ü ßܱ
²Ü  ßß °²±²ÛÛÛÛÛÛÛÛÛÛÛÛ 
 ÞÜÞÛÛ²ÛÛ²Û
 ° °°Û°°°ÝÞÛ 
Þ²±°±°° ²±±±±±²±²Ý±²
Þ²Û²Û²Ü ßßß ÜÝ
° ±°±²ÛÛÛÛÛÛÛÛÛÛÝ ² Û²
ÛÛÛÛÛÛ
° Ý Þ°±°Û ÛÝ ²±
°±±°± Þ±±±²±²²²² ±Üß
ÛÛÛ²²ÛÛÛ²° ° ²ÛÛÛÛÛÛÛÛÛß °
Þ ÞÛÛÛÛÛ²ÛÛ
° °  ±Û° ÛÞÛ
Þ±±±±±±± Þ±²²±²²²Û²ÛÜ
 ßÜß²²ÛÛÝÞÛ²° ²ÛÛÛÛÛÛ
ß Ü   ÛÛÛÛÛÛÛÛÛ
±°°°Ý°Þ ÝÞ°
 ²±±±²±±± Þ²±²²²²Û²Û
ÛÛÛÛÜ þ ßß²Û²±° ° ²Ûßß
 Üܲß ° ÛÛÛÛÛÛÛÛÛÛ
±°±°° °ÛÝ°Ý
Þ±±²±²²±± Þ²²²²Û²Û
ÛÛÛÛÛ² ° Ü °  ²Û²±°
 Üܲßßß  ° ÛÛÛÛÛÛÛÛÛÛÛ
²±²±²²° ÛÞÛÝÞ²±²²Û
²±²Ý°²Û²ÛÛÛÛÛÛÛ²± ° ²Ûß
 ß  þ °Ü °  ßß
 ° °±Ý°ÞÛ²ÛÛÛÛÛÛÛÛÛ
Û²²²²²Ü° ß  ²²
Û²ÛÛ²ÛÝ ²ÛÛÛÛÛÛ
ÛÛ² ° ±²Û°   ÛÛÛ²Û² ° °±°
  Þ²²ÛÛÛÛÛÛÛÛ²
ÛÛÛ²Û²²Ü °Ü
 ° ²ÛÛÛÛÛÛÝ
ÛÛÛÛÛ²Û² ° ²Ûß°° °
  ÛÛÛ²Û²± ° ° ± ±²²ÛÛ²ÛÛ²±
Û²ÛÛÛÛÛÛÞ°Û ²ÜßÛ
²ÛÛÛ² Þ²Û²²±° ° °²Ûß  °
 °±°° ° 
ßÛÛÛ²Û±±° ÞÝ ° ±° ° ßß
²±²Û²Û²ÛÞ±° ÜÜ þ
ßßÛÛ±ÝÞ²²± ° °²²ß ° 
 ° ±²±°±°°  ßÛÛÛ²Û
±²± ²Ý ° °±° ° 
± ±²±²±²Ý²°Ý ²Û²ÛÜÜܲ±²
 ± ° ±²²ß ° °°°°°
²±²±²±°±° ° ßÛÛ۲۲ݱ Ü°
 ° °° 
²° ° ° ß° °Ý Þ²±Û²Û²±°
Þ  °²±²²ß ° °°±°± °
 ° ²²²²±²±±±°±° ßßÛ
ÛÛ °Þ²Ý ܲÛÜÜÜÜܲ
Ûܲ²°±°²±°Üß °°²±²±° ²
°²Û²ß °°°°°°±°±² ±±°°Þ²Û²²²²±²±±± °
ß Û²± ÞÛÛÛÛÛÛÛÛ
²ÛÛÛܲÛܲ±²²ÜÜ °°±²Ý± ²Ý ß ° °
°±°±²±²± ±²² ²ÛÛÛ²Û²²²±²±±±°±
   ° ßß²ÛÛÛ²Û
ßß²ÛÛÛ²ÛÛ²ÛÛ²Û²Üܲ۲°ß °  ° °±°±
±²±²²±²²Þ²²Û ÛÛ²ÛÛÛÛ²Û±²²±²±±°° 
Ý °±°  °   
 ßßßßßßßßßßß±°±²±²²²²²Û²Û²
²Û²ÞÛÛÛÛÛÛÛÛÛ²Û²²±²²± ± °°°°° °± ܱ
²S™
 °°° ° ±²Û²Û²ÛÛÛÛÛÛÛÝÛÛÛÞÛÛÛ²
ÛÛ²ÛÛÛÛÛÛ²Û²² ±°±° ±±²²±²Û²±
°°° °°° ° ° °
 ° ° Ü  ±²²ÛÛÛÛÛ²Û
²ÛÛÞÛÛ² ÛÛÛ²Û
²ÛÛÛÛÛÛÛÛÛ²ÝÞ ±²±± °²²ÛÛ²ÛÛÛ²
° °°°°°°±°°±°±±° °±±²Ý  Þ²ÛÛÛÛÛ²
ÛÛ²²ÛÞÛÛÛݲÛ²Û²²²ßÛ
²ÛÛÛÛÛÛ ² ²Û²²±²ÛÛÛÛÛÛÛ²Ü
°° °° °°°±° °° ± ß  ß 
ßß ß    ß
ßßßßß
ßß ÞÝßß ßßßßßß ß 
° ° °° °
   °°°  ±°
 °Ü°°Ü°±° ° °
°Ü°° °°Ü±°°
°Ü°  ° °°Ü°°
±° °Ü Ü°
   Ü ܱܲÜ
²±Ü²²ßܲßÛÜ ß߲ܲ߰²ßÛ²Ü߲߲ܲ²ß²±²ÜÜß
Û±²Û° Þ Ü°²ß±²
ܱ°Üß߲ܰ²Ü
  °ß° ß ß°
° °°ß°° ±²°°  
 °Ü± °± °°  ° °
 °  ° °± °
° ° ° °±°
ß°° °° ±
²Ü²ÜÜßÜßÛ²ÜܲßÜß²Ü  ßܲßß²Ü
߲߲ÛÜß²ÛܲÜß߲߲߲ܲß ²
ßܲ°±ßܲ²±ß°
߲ܲ°Ü
°ß°°ß°ß±° °±
 °ß °°ß²° °°
° °± °ß °°
°°°°ß° ±°ß °
 ÞÝ ° ß °±
 ° °° ±²ß
°ß°
 Ü ÜÜÜÜÜÜ ÜÜÜܲÜÜ
  ÜÜÜÜ²Ü ÜÜÜÜÜÜÜÜÜÜÜܲÜÜÜÜ
ÜÜÜ ° ÜÜÜÜ
ÜÜÜÜÜÜÜÜÜ  ß þ
 Üß ° ° ° °° °°²
  ܱ° ÜÜÜÜ Ü²Ü±°±° ° ° Ý
Þ  ° Ü °Ü±°° ° ß 
ß
Þ°ÜÜܲ±° °° °°±±²²Û²
 ÞÛ°ÞÛÛÛÛ²ÛÛ²Û²²
²±²±±°±° °Û ±Þ°°
ÛÛÛÛÛÛÛÛ²²±±° ° °°
ÛÛÛ²±°° °°°±±²Û²ÛÛÝ
ÞÛ°°ÛÛÛÛÛÛ²Û²²²²²²²±°
°±°  ° ²°ÞÛÛÛÛÛÛÛ²
Û²²±±±±°±°
ÞÛÛ²²±°° °°°±±²±²ÛÛÛÛ  Û
°°ÛÛ²ÛÛÛÛ²Û²²²²±²±±±°Ý
ÜÜ Þ±°ÛÛÛÛÛÛ²ÛÛ²
²±²±²±±°°
ÛÛÛ²±°°°°°°°±±²±²Û²ÛÝ°
ÞÝ°ÞÛÛÛÛ²Û²²²±²²±±±±°±
 °Üß °ÛÛÛ
²ÛÛÛÛÛ²Û²²²²±²±±°
ÞÛÛÛ²±°° °°°°°±²Û²ÛÛÛ
° ß°Û²Û²Û²²²²²
²±±°±°ß ܲ
ÜÜÛÛÛÛÛÛÛÛÛ²Û²²²±²
±±±±°
ÛÛÛÛ²±°°°°°°±±±²²ÛÛÛÝß²Ü
±²²²²²²±²±±°±±° Û±Ü
ßþÞÛÛÛÛÛÛÛÛÛÛÛ²²±±²±±±±°°
ÞÛÛÛ²±°±°°°°°±±±²²ÛÛÛÜßܲ
Üß²ßßß±±±±°±°
ßÜÛ²² ÜÜÛÛÛÛÛÛÛÛÛ²Û
²±²²±±±°±°° 
ÞÛÛÛ²²±°°°°°°±°±±²±²ÛÛÛÜßß±
°ß ß ßßß
. ß ±ÛÛÛÛÛÛÛÛÛÛ²²²²²²±
±°±±°°° 
ÛÛÛ²²±°° °°°°±±²²Û²ÛÛÛÛÛÛ
²Üß ß° ²Üþ
 ß ° ÜÜ
ÛÛÛÛÛÛÛÛ²ÛÛÛ²²±²±±±±°°°° 
ÛÛÛÛ²±° °°°°±°±±²Û²ÛÛÛÛÛÛÛÛ
²²±Ü ÜÜ
ÜÜÜÜÛÛÛÛÛÛÛÛÛÛÛÛ²²²±²±±±°°
°°° 
ÛÛÛÛ²±°° °°°°±±²±²ÛÛÛÛÛÛÛÛÛÛ²±°°
 ±Þ°±°±²ÛÛÛÛÛÛÛÛÛÛÛÛÛ
²²²±±±±±°°°°° ° 
ÜÛÛÛÛ²±°°°°°°°°°±±±²ÛÛ²ÛÛÛÛÛÛÛ
Ûß²±ÝÞ² °ß
±²²²ÛÛÛÛÛÛÛÛÛÛÛ²Û²²²±°±
°±°°° 
ÜÛÛÛÛÛ²±°° °°°°°°±±±²²²ÛÛÛÛÛÛÛßß
ßÜÜܲ°±Üß ß
²²²ÛÛÛÛÛÛ²Û²²²²±²±±±±±°°°°° ° 
Ü ÛÛÛÛ²²±°°°°°°°°°±°±²Û²ÛÛÛÛÛÛÛÜ
ßßÛ°±²Ü°°Ü
°±° ßß ÛÛÛÛÛÛÛÛÛÛ²²²²²±²±
±±±°±°°°° 
Ü°°° Û²²±°±°°°°°°±°±±±²ÛÛÛÛÛÛÛÛÛÛ
ÛÛÜÜ ß±Üßß°°ß
ÜܲÛÛÛÛÛÛÛÛÛÛÛÛ²
²²²²±±²±±±°±±°°°
°°±±² ±°°±°°°°°±°°±±²±²²Û²
ÛÛÛÛÛÛÛÛÛ²²ßÜ ß
°±ßÝß Ü²ÛÛÛÛÛÛÛÛÛÛÛ
Û²Û²²²²±²±±±±±±°°° 
±±²²²Û °°°°°°±°±±±±²±²²ÛÛÛÛ
ÛÛÛÛÛÛÛ²²Üß ÜÝÞ²
  ܲ²²ÛÛÛÛÛÛÛÛÛÛÛ
ÛÛ²Û²²²±±±±±°°°° 
²²ßÛ²   °°°±°±±±±±±²²
²Û²ÛÛÛÛÛÛÛÛÛ²Û²²²±°Ý
ÞÝ  ²²±±²Û²Û
ÛÛÛÛÛÛÛÛÛÛÛ²²±±±±±±±±°° 
²Û°ß ܱ 
°°°±±±°±²±²²Û²ÛÛÛÛÛÛÛÛÛÛÛ²²²±²±°
Þ ÝÞ°±²±±²ÛÛÛÛÛÛÛÛÛÛÛÛ
²²²²±²²±±°±°°° 
ß ÜÛ°ß °
°°°±±±±±²²ÛÛÛÛÛÛÛÛÛÛÛÛÛ²²²±°±° 
ÝÞÛÞ±²±²±±²ÛÛÛ²
ÛÛÛÛÛÛÛÛ²²²²²±±±±°°° ° 
 ÜÛ°ß ÜÜÜ
 °°±±²±²²²²ÛÛÛÛÛÛÛÛÛÛÛÛ²²±²±°
° ßß±±²²±²²²ÛÛÛÛÛÛÛÛÛ
²²²²²±±±±±±°°° 
²ßß °Ü²Û²ß 
°±±±²²²ÛÛÛÛ²ÛÛÛÛÛÛÛÛ²²²
±±±° ßÜ°Þ°²²²±±²ÛÛÛÛÛÛÛÛ
²ÛÛ²²²²±²±±±±°°°° 
ÜÜÛ°±ßß Ü²
°±²²²Û²ÛÛÛÛÛÛÛÛÛÛÛÛÛ²²²
±°°° ݲܲ°±²²±±²²²ÛÛÛÛÛÛÛÛÛ
Û²²²²²±±±±°±°°°°
ÛÛÛ°ß Üܲ²²² ±±
²²²Û²ÛÛÛÛÛÛÛÛÛÛÛ²Û²
±±±°°° Ü°°±²²±±²±²ÛÛÛÛÛÛÛÛÛ
Û²²²²²±±±±±±±±°°  ²ßß Ü²
²²²²²²² ±±²Û²ÛÛÛÛÛÛÛÛ
ÛÛÛÛÛ²²²±±±±°°²Ü°°±±°±±²Û
²ÛÛÛÛÛÛÛÛÛ²²²²²²±±±±±°±±°°
 ܲ²²²²²²²²²²² ±²²²Û²
ÛÛÛÛÛÛÛÛÛ²ÛÛ²±²±±°±°°°°±°±±±²²²ÛÛ
ÛÛÛÛ²ÛÛ²²²²²²±±±±±±±±±°°
Þ²²²²²²²²²²²²²²² ±²±²²Û²
ÛÛÛÛÛÛ²Û²²²±±±°°°° °°°±±²²²²ÛÛÛÛÛ
ÛÛÛÛ²²²²²²±²±±²±±±±°±°
²²²²²²²²²²²²²²²² ±±±²²±²Û²
Û²²±²²±±±±°±°° °°±±²²Û²ÛÛßßßßÛ²Û
²²²²²±²²±²±±±±±±±°°
Þ²²²²²ß ÜÜÜÜÜÜÜÜÜÜÜÜÜ ß
 ÜÜÜÜÜÜÜÜÜÜÜÜ ß ÜÜÜÜÜÜÜÜÜÜÜÜÜ ß
Ü  ÜÜÜÜÜÜÜÜÜÜÜÜÜ ß±
±±±±°
Ý ²²²²² Ûß°ÛÜ
Û Ü ÛÜÛß°Û Û
ß±ÜÛ Ü ÛÜÛ
°ßÛ ÛÝ °ÜÛ Ü Û
ܱÛßÛ Ü Ûß±ÜÜÛ
Ü ÛÜÛß°Û ±±°±°°
° Þ²²²² ÛÜÛÛÛÛ
 ² ßÛÛÛÛß
 ßÛÛÛß ° ÛÛÛÛÛÛ ßÛ
ÜÜÛß ± ÛÛÛÛÛ
Û ² ÛܱÛÛÛ
ß ßÛÛÜÛß ±°°
ßß
±Ý ²²²² ÛÞ²ÛÛ
Û ²ß ÜÜÜÜ ß ÜÜÜÜÜÜ
ÛÛÛÛÜÛ ÜÜÜÜÜÜ°± Û
ÛÛÛÝÛ ±Ü
 ßßßßßßÜÜÜÜÜÜ ßß Ü
 °Ü
²Ý ²²²² Û ±ÛÛ
Û ² ÛÛܲßÛ ÛÛÛÛÛ
Ü ÛÛÛÛÝÛ  ° °°°°
 ÛÛÛÛ°Û ±
ÜÛÛÛÛÜ Ü ÛÛÛßÛÛ
°±²ÝÞ²
Û² Þ²²² Û° ÜÛ
Û ² ÛÛÛÛ°Û Û
ÜÛÛÛ ° ÛÛÛß°
Û ° ° °°° ÛÛß °Û
° ÛßÛÛÛÛ ß
 ÛÛÛÝ°Û ±²ÛÛ
ß
ÛÛ Þ²²² Û±ßÝßÛ
 ² ÛÛÝß±Û Û±ß
ÞÛ   ÛÛÜ°±Û
 °°° ° ÛÝÞܱÛ Û
 Û±ÞßÛÛ ° ÛÛ
ßÛ±Û ²ÛÛÛÝÞ
ÛÛÝ ²²² Û²±°ßÛ 
ß Ûß°±²Û Û²±ßÛ
ß Ûß°±²Û  ° ° °°
 ÛÜ °²Û ² Û²
±°ßÛÜÜÜÛßß°²Û Û²Û²²
ÛÛÝ ²²²Ü ßßßßßßßßßßßßß
Ü ßßßßßßßßßßßß Ü 
°Ü ßßßß  ß
  ßßßßßßßßßßßßß ܲ±²ß°°
ÛÛ² Þ²²²²²²²²²²²²²²²²²²²²
² ° °° ° ²ß
ÜÜ°±²²²Û²²Û²ÛÛÛÛ²Û²±²±Ü
Üß 
Û²ß ÜÜÜÜÜÜÜÜÜÜÜÜÜ ß ÜÜÜÜÜÜÜÜÜ
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ß ÜÜÜÜ ß²
ß ÜÜÜÜÜÜÜÜÜÜÜÜÜ ß²
Û² Ûß±ÛÜÛ Ü 
ÛÜÛ°ÞÛ ÛßÛÜ
ÛÛ Ü Û±ßÛÜÛ Ü
 ÛÛß°ÜÛ Ü ÛÜ
Û±ßÛ Ûß°ÜÛÛ Û
Ûß°ÛÜÛ  
ÛÜÛß°Û °
²² ÛßÛÛÛÛ ²
ßÛÜÜÛß ÛÞÛÛÛÛ
² ßÛÜÛÛß ²
ÛÛÝÞÛÛ ß ÛÛÛÛÝ
Û ÛÛÛÛÛÛ ² Û
²ÛÛÛÛ ß ßÛÛÜÛß
 ±
²² ÛÛÛÛÛÛ ²ß ÜÜÜÜ
  ÛÛÛÛÛÛ ²ß ÜÜÜÜÜÜÜ
ÛÛÛÛÛÛ ° ÛÛÛÛÛÛ Û²
ÛÛÛÛ   ÛÞÛÛÛÛßß ÜÜÜÜ
 ß±
²± ÛÝÛÛÛÛ ² ÛÛÛ
ÜÛÛ ÛßÛÛÛÛ ²
ÛÛÜÛÛÛ Ü ÛÛÝÛÛÛ
 ± ÛÛÛÛÝÛ ÛÛÛÛÛÛ
± Û±ßÛÛÛ   Û
ÛÜÛÛÛ ±
±± Û°ßÛÛÛ ²
 ÛÛÛÛ°Û Û°ßÛÛÛ
² ÛßÞÛÛÛ ß
ÛÛÝÛÛÛ ² ÛÛÛÝ°
Û ÛÞÛÛÛÛ Û  ßßßß
Ü° ÛÛÛÛÝÛ
²
²± Û±°ßÛÛ ²
ÛÛÛÝßÛ Û±ÞßÛÛ
² Û±ÞÛÛÛ ±
 ÛÛÜ°ÛÛ ² Û
ÛÝß±Û Û°ßÞÛÛ Ü
 ÜÛÛÛÛÜ ° ÛÛÛß±Û
 ±
±± Û²±°ßÛ ß Ûßß°Ü
Û Û²±±ßÛ ² Û²°
ß²Û ß Ûß°±ßÛ ß
 ÛÛß°²Û Û²±°ßÛ ß
 ÛÛßß±Û ß Ûß°±²
Û ²
±°Ü ßßßßßßßßßßßßß Ü
ßßßß Ü²Ü ßßßßßßßßßßßßßßßßß
ßßßßß   ßßßßßßßßßßßßßß ßßßßßßß
ܲ
±°±°Û ²²²²²²²²²²²²²²²²²²²²²²²²
۲ݰ±²²²²²²²²²Û²Ûß²ÜÛ°ß
Ü °°°±°±±°±±²²±²²²±²²²²²² 
±±°±° Þ²²²²²²²²²²²²²²²²²²²²²²Û²Þ
°±²²²²²²²²Û²Ûß²±±ßß 
Ü °°±°±±±²²±²²²²²²²²²²²²²²²
SAUCE00Cat's Cradle Somms ACiD Productions 19950601°ÀP«

22
mods/art/we-wrong.ans Normal file
View File

@ -0,0 +1,22 @@
[?33l
  <20><> <30><6D><EFBFBD>   <37> <37><6D><EFBFBD>
 <20>߲<6D><30><6D> Mr.  <20><37><37><30><6D><30><31>   <30><6D> <30><6D>    <30><6D>   <20><><37><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 <20><37><30>۲<30> ܲ<34><34>  <30><6D><37><6D><EFBFBD><EFBFBD><37><30><31> <34>  <34><6D>  <30><37><6D> <30><37><6D><37>  <37>߲<EFBFBD><DFB2><EFBFBD> <34><6D> ߲<6D><37><6D><30><30><37><6D><EFBFBD><EFBFBD><37>  <37>   <20><><EFBFBD><34>
 <20><37><6D><EFBFBD><30><30> <34><34><6D><EFBFBD>  <20><><37><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><37><30> <30><36> <34>    <37><6D><EFBFBD><EFBFBD><EFBFBD>  <30><37><6D><EFBFBD><EFBFBD><EFBFBD> <37>  <34><34><34> <20><37><6D>۲<30><31><6D><EFBFBD>۲<30><31>  <20><><34>ܲ<34>
 <20><37><6D><EFBFBD><EFBFBD><EFBFBD><30> <34>  <20><><30><37><6D><EFBFBD><30><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><37><30> <20><36> <31>ܲ<6D><DCB2><EFBFBD><EFBFBD>۲<EFBFBD> <37><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <31><6D><EFBFBD>  <20><36><36><30><6D><37><36><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><36> <34><34><6D><EFBFBD><EFBFBD>
 <20><36><30><6D><36><6D>  <20><><36><37><6D><EFBFBD><EFBFBD><EFBFBD>  <37><36><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><37><30> <37><6D><EFBFBD><EFBFBD><30> <30><37><6D><EFBFBD><EFBFBD> <37><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><36> <20><31><6D><36> <36><30><6D><EFBFBD><36> <31><6D><36><30><6D><EFBFBD><36><36>   ߱
  <36><6D><EFBFBD><EFBFBD><36> <34><6D><EFBFBD>  <36><6D><EFBFBD><30> <20><><EFBFBD><36><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <36><6D><EFBFBD><EFBFBD> <34> <20><31><6D><36><30><36><6D><36><6D><EFBFBD><EFBFBD><30><36><36> <20><34>  <20><><36><6D> <20><><EFBFBD><36><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܲ<30>
 <36><30><6D>ܲ <34> ܲ<6D> <36><36><30><6D><EFBFBD> <20><36><6D><36><6D><36><6D><EFBFBD><EFBFBD><EFBFBD><36><32><6D><EFBFBD><EFBFBD> <34> <32><6D><EFBFBD><EFBFBD><36><36><6D><30><36><36><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><36>  <31><6D><EFBFBD><36><30>  <20><36><6D><30> <36><36><6D><EFBFBD><EFBFBD><EFBFBD><30>
 <20><36>۲<EFBFBD> <31><36> <20> <36><6D><36><6D><EFBFBD> <20><36><6D>ܲ <36>۲<36> <32><6D><EFBFBD><EFBFBD> <34> <32><6D><EFBFBD><30> <32><6D><36><30><30><36><36><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><36><6D><36><6D><EFBFBD><EFBFBD><30><36><6D><30><32><6D> <20> <36><31><6D><36> <34><6D>
 <32><6D><EFBFBD><EFBFBD><EFBFBD> <36> <20><34><30> <36><6D><EFBFBD><EFBFBD><EFBFBD>  <36><32><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><36> <20>  <32><6D><EFBFBD><32><31><6D><32><6D><32>  <32><6D><EFBFBD><EFBFBD><30> <20><36><36><32><6D><EFBFBD><EFBFBD><EFBFBD><36><30><6D><EFBFBD> <36><32><6D><EFBFBD><EFBFBD> <30><32><6D>  <32><6D>
  <36><6D><EFBFBD><EFBFBD><EFBFBD> <20><32><6D><EFBFBD><32> <36><6D><EFBFBD><EFBFBD><EFBFBD> <20><32><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><32><34> <20><> <32><6D><EFBFBD><EFBFBD><EFBFBD><30><30><6D> <36><6D><EFBFBD><EFBFBD><30><34><31><30> <32><6D><36><6D><EFBFBD><EFBFBD><EFBFBD><32><30> <31><32><6D><EFBFBD><EFBFBD> <30><32><32><6D><EFBFBD><32><6D><EFBFBD><EFBFBD> 
 <32><6D><EFBFBD><EFBFBD><32><31><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><32><36><6D><EFBFBD><EFBFBD><30><36><6D><32><6D><32><36><32><6D><EFBFBD><EFBFBD><EFBFBD>ܰ<6D><DCB0><EFBFBD><EFBFBD><37><30> <30><32><30> <32><6D><36><6D><30> <20><32><32><6D><30><32><6D><36><6D><EFBFBD><EFBFBD><EFBFBD><32><36><32><6D><32><6D> <30>  <32><31><6D><EFBFBD><EFBFBD><EFBFBD>
  <32><6D><EFBFBD><32><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><30><32><31> <32><32><32><6D><EFBFBD> <30><32><32><6D><EFBFBD><EFBFBD><EFBFBD><32><6D><32><6D><EFBFBD><32><34><6D><30> <31><6D><32><6D> <32><6D><31><6D> <30><6D><32><30><6D><EFBFBD><EFBFBD><32> <32><6D><EFBFBD><EFBFBD> <20><><EFBFBD>ܲ<6D><DCB2><32><31><6D>
 <32><6D><32><6D><EFBFBD><EFBFBD><EFBFBD>۲<30><32><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۲ <32><6D><EFBFBD><EFBFBD><EFBFBD> <20><><32><32><30><6D><EFBFBD><32><6D><EFBFBD><EFBFBD><EFBFBD><30><6D>߰ <20><32><30><6D><EFBFBD><32> <20><32> <30> <32><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۲ <32><32><30><6D><EFBFBD><EFBFBD><32><32> <20>
 <31><6D><32><6D><EFBFBD>۲<32> <32><6D><32><6D><EFBFBD>۲ <32><6D><EFBFBD><EFBFBD><EFBFBD> <34><6D> <30><6D><32><6D><32><6D><30><6D><EFBFBD><EFBFBD><EFBFBD><32><30>  <31><6D><EFBFBD><EFBFBD><32><6D><32> <30><32><6D><EFBFBD><EFBFBD> <31><6D><EFBFBD><EFBFBD><32><30><32><6D><EFBFBD><32><32><30><6D><EFBFBD><EFBFBD><EFBFBD><32><6D><32><30><32>
<31> <20><32><6D><EFBFBD><32><6D><32><30> <30><6D><32><6D><EFBFBD>߱ <32><30><6D><32><6D><30><30><6D>   <37><6D><32><6D><32><6D><30><6D><EFBFBD><37><6D> <32><6D><EFBFBD><EFBFBD><32>   <32><6D>۲<EFBFBD><DBB2>۲<30> <20><32><30><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><32><6D><32><32><6D><EFBFBD>
<32><6D><EFBFBD><EFBFBD><EFBFBD>۲<32><30> <32>  <30><6D><32><30><32> <32><6D><32><30><30><30>  <20><><EFBFBD> <20><><32>߲<6D><DFB2><EFBFBD><30><32><6D><30><30><32>  ܰ <30><6D><30><32><6D><EFBFBD><32><30><6D>  <32><30><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <30> <32> <32><31>
 <30><32><30><6D><EFBFBD><EFBFBD><EFBFBD><32><30><32><30>    ߱<6D> <30>ܱ<6D>  <34><6D><EFBFBD><34>߰ <20><30><6D><EFBFBD><30>  <30><30> <34><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD>  <30><6D> <30><30> <32><32><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <30><32><31>No!
<30><6D><32><31><32><6D><30><32><37><6D> <34><31><34><34>    <20><> <34><6D><EFBFBD><34> <34><6D><EFBFBD><34><6D><EFBFBD><EFBFBD><31><34>߲ <34><6D><EFBFBD>  <20> <20><>  <32><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><30> k1.<34><6D>
 <30><6D><30><37><6D><30> <34><31><34> <34>   <20><> <34><34><34><6D> f r 3 d <20> <20><34> <34> <20>  <31> <20> <20><><30><6D>
<34> <34><34><6D> <20><>

74
mods/art/zO-theGhetto.ans Normal file

File diff suppressed because one or more lines are too long

55
mods/connect.js Normal file
View File

@ -0,0 +1,55 @@
/* jslint node: true */
'use strict';
var ansi = require('../core/ansi_term.js');
var artwork = require('../core/art.js');
var modules = require('../core/modules.js');
var packageJson = require('../package.json');
var util = require('util');
exports.moduleInfo = {
name : 'Connect',
desc : 'First module upon connection',
author : 'NuSkooler',
};
exports.entryPoint = entryPoint;
function entryPoint(client) {
/*var self = this;
this.client = client;
var term = this.client.term;*/
var term = client.term;
term.write(ansi.normal());
term.write(ansi.disableVT100LineWrapping());
// :TODO: set xterm stuff -- see x84/others
// :TODO: add URL to banner
term.write(ansi.fromPipeCode(util.format('' +
'|33Conected to |32EN|33|01i|32|22GMA|32|01½|00 |33BBS version|31|01 %s\n' +
'|00|33Copyright (c) 2014 Bryan Ashby\n' +
'|00', packageJson.version)));
setTimeout(function onTimeout() {
term.write(ansi.clearScreen());
artwork.getArt('CONNECT', { random : true, readSauce : true }, function onArt(err, art) {
var timeout = 0;
if(!err) {
term.write(art.data);
timeout = 1000;
}
setTimeout(function onTimeout() {
term.write(ansi.clearScreen());
modules.goto('matrix', client);
}, timeout);
});
}, 500);
}

36
mods/matrix.js Normal file
View File

@ -0,0 +1,36 @@
/* jslint node: true */
'use strict';
//var art = require('../core/art.js');
var ansi = require('../core/ansi_term.js');
var lineEditor = require('../core/line_editor.js');
var art = require('../core/art.js');
exports.moduleInfo = {
name : 'Matrix',
desc : 'Standardish Matrix',
author : 'NuSkooler',
};
exports.entryPoint = entryPoint;
function entryPoint(client) {
var term = client.term;
term.write(ansi.clearScreenGoHome());
// :TODO: types, random, and others? could come from conf.mods.matrix or such
//art.getArt('SO-CC1.ANS'/* 'MATRIX'*/, { types: ['.ans'], random: true}, function onArt(err, theArt) {
art.getArt('DM-ENIG2-MATRIX.ANS', {}, function onArt(err, theArt) {
if(!err) {
art.display(theArt.data, { client : client, mciReplaceChar : ' ' }, function onArtDisplayed(err, mci) {
if(err) {
return;
}
console.log(mci);
});
}
});
}

5
package.json Normal file
View File

@ -0,0 +1,5 @@
{
"name" : "enigma-bbs",
"version" : "0.0.1-beta",
"description" : "ENiGMA½ Bulletin Board System"
}