From 9aa91a4410d5894d60ea8871041ce6a2b10dbe27 Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Wed, 8 Feb 2012 22:13:44 -0500 Subject: [PATCH] Snapshot --- basic.js | 2411 +++++++++++++++++++++++++++ bell.js | 55 + bell.mp3 | Bin 0 -> 1880 bytes bell.ogg | Bin 0 -> 4844 bytes bell.wav | Bin 0 -> 33568 bytes cm2/mode/basic/basic.css | 46 + cm2/mode/basic/basic.js | 222 +++ dos.js | 509 ++++++ feed.js | 66 + feed.xml | 789 +++++++++ font-40col.png | Bin 0 -> 19128 bytes font-80col.png | Bin 0 -> 4387 bytes font.png | Bin 0 -> 3872 bytes hires.js | 152 ++ index.htm | 452 +++++ lores.js | 192 +++ paddles.js | 140 ++ printer.js | 95 ++ reference.htm | 570 +++++++ samples/TRADER C.txt | 302 ++++ samples/sample.adventure.txt | 254 +++ samples/sample.basic.txt | 291 ++++ samples/sample.bitmaps.txt | 408 +++++ samples/sample.bodymass.txt | 32 + samples/sample.boys_surface.txt | 25 + samples/sample.charset.txt | 23 + samples/sample.connections.txt | 9 + samples/sample.default.txt | 1 + samples/sample.february.txt | 25 + samples/sample.gaussian.txt | 47 + samples/sample.hacker.txt | 48 + samples/sample.hangman.txt | 613 +++++++ samples/sample.hellosine.txt | 6 + samples/sample.hireswalk.txt | 34 + samples/sample.jot.txt | 168 ++ samples/sample.keyboard.txt | 9 + samples/sample.loreswalk.txt | 12 + samples/sample.mandelbrot.txt | 10 + samples/sample.mandelbrot2.txt | 14 + samples/sample.pacman.txt | 245 +++ samples/sample.paint.txt | 23 + samples/sample.primes.txt | 29 + samples/sample.puzzler.txt | 85 + samples/sample.raindrops.txt | 199 +++ samples/sample.readsector.txt | 11 + samples/sample.rodscolorpattern.txt | 11 + samples/sample.scribble.txt | 24 + samples/sample.sectorgen.txt | 423 +++++ samples/sample.sierpinski.txt | 24 + samples/sample.squiggle.txt | 35 + samples/sample.steve.txt | 71 + samples/sample.stringart.txt | 11 + samples/sample.unittests.txt | 812 +++++++++ samples/sample.zhorelay.txt | 107 ++ samples/simple.pong.txt | 142 ++ styles.css | 968 +++++++++++ tty.js | 904 ++++++++++ vfs/DATAFILE.txt | 26 + vfs/JABBERWOCKY.txt | 4 + vfs/OD JUMP.txt | 169 ++ vfs/SHIPS.txt | 28 + vfs/SHIPS@.txt | 39 + vfs/SOLOMANI.txt | Bin 0 -> 20795 bytes vfs/SOLOMANI@.txt | 23 + vfs/SOLOMANI_MAP.txt | Bin 0 -> 2926 bytes vfs/SPINWARD.txt | Bin 0 -> 22235 bytes vfs/SPINWARD@.txt | 21 + vfs/SPINWARD_MAP.txt | Bin 0 -> 3560 bytes 68 files changed, 12464 insertions(+) create mode 100644 basic.js create mode 100644 bell.js create mode 100644 bell.mp3 create mode 100644 bell.ogg create mode 100644 bell.wav create mode 100644 cm2/mode/basic/basic.css create mode 100644 cm2/mode/basic/basic.js create mode 100644 dos.js create mode 100644 feed.js create mode 100644 feed.xml create mode 100644 font-40col.png create mode 100644 font-80col.png create mode 100644 font.png create mode 100644 hires.js create mode 100644 index.htm create mode 100644 lores.js create mode 100644 paddles.js create mode 100644 printer.js create mode 100644 reference.htm create mode 100644 samples/TRADER C.txt create mode 100644 samples/sample.adventure.txt create mode 100644 samples/sample.basic.txt create mode 100644 samples/sample.bitmaps.txt create mode 100644 samples/sample.bodymass.txt create mode 100644 samples/sample.boys_surface.txt create mode 100644 samples/sample.charset.txt create mode 100644 samples/sample.connections.txt create mode 100644 samples/sample.default.txt create mode 100644 samples/sample.february.txt create mode 100644 samples/sample.gaussian.txt create mode 100644 samples/sample.hacker.txt create mode 100644 samples/sample.hangman.txt create mode 100644 samples/sample.hellosine.txt create mode 100644 samples/sample.hireswalk.txt create mode 100644 samples/sample.jot.txt create mode 100644 samples/sample.keyboard.txt create mode 100644 samples/sample.loreswalk.txt create mode 100644 samples/sample.mandelbrot.txt create mode 100644 samples/sample.mandelbrot2.txt create mode 100644 samples/sample.pacman.txt create mode 100644 samples/sample.paint.txt create mode 100644 samples/sample.primes.txt create mode 100644 samples/sample.puzzler.txt create mode 100644 samples/sample.raindrops.txt create mode 100644 samples/sample.readsector.txt create mode 100644 samples/sample.rodscolorpattern.txt create mode 100644 samples/sample.scribble.txt create mode 100644 samples/sample.sectorgen.txt create mode 100644 samples/sample.sierpinski.txt create mode 100644 samples/sample.squiggle.txt create mode 100644 samples/sample.steve.txt create mode 100644 samples/sample.stringart.txt create mode 100644 samples/sample.unittests.txt create mode 100644 samples/sample.zhorelay.txt create mode 100644 samples/simple.pong.txt create mode 100644 styles.css create mode 100644 tty.js create mode 100644 vfs/DATAFILE.txt create mode 100644 vfs/JABBERWOCKY.txt create mode 100644 vfs/OD JUMP.txt create mode 100644 vfs/SHIPS.txt create mode 100644 vfs/SHIPS@.txt create mode 100644 vfs/SOLOMANI.txt create mode 100644 vfs/SOLOMANI@.txt create mode 100644 vfs/SOLOMANI_MAP.txt create mode 100644 vfs/SPINWARD.txt create mode 100644 vfs/SPINWARD@.txt create mode 100644 vfs/SPINWARD_MAP.txt diff --git a/basic.js b/basic.js new file mode 100644 index 0000000..8045c7e --- /dev/null +++ b/basic.js @@ -0,0 +1,2411 @@ +// +// Applesoft BASIC in Javascript +// BASIC Compiler +// + +// Copyright (C) 2009-2011 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// API: +// var program = basic.compile(source); +// // may throw basic.ParseError +// +// program.init({tty: ..., hires: .e.., lores: ...}) +// +// // if TTY input is blocking: +// +// var state; +// do { +// state = program.step(); +// // may throw basic.RuntimeError +// } while (state !== basic.STATE_STOPPED); +// +// // if TTY input is non-blocking: +// function driver() { +// var state; +// do { +// state = program.step(driver); +// // may throw basic.RuntimeError +// } while (state === basic.STATE_RUNNING); +// } +// driver(); // step until done or blocked +// // driver will also be called after input is unblocked +// // driver may want to yield via setTimeout() after N steps + +// Functions from polyfill.js, via jsmin, for running via console +if(!Object.keys){Object.keys=function(o){if(o!==Object(o))throw new TypeError();var ret=[],p;for(p in o)if(Object.prototype.hasOwnProperty.call(o,p))ret.push(p);return ret;};} +if(!Array.prototype.forEach){Array.prototype.forEach=function(fun){if(this===void 0||this===null){throw new TypeError();}var t=Object(this);var len=t.length>>>0;if(typeof fun!=="function"){throw new TypeError();}var thisp=arguments[1],i;for(i=0;i>>0;if(typeof fun!=="function"){throw new TypeError();}var res=[];res.length=len;var thisp=arguments[1],i;for(i=0;i>>0;if(typeof fun!=="function"){throw new TypeError();}if(len===0&&arguments.length===1){throw new TypeError();}var k=0;var accumulator;if(arguments.length>=2){accumulator=arguments[1];}else{do{if(k in t){accumulator=t[k++];break;}if(++k>=len){throw new TypeError();}}while(true);}while(k= 2) { + throw new basic.RuntimeError(msg[1], msg[0]); + } else { + throw new basic.RuntimeError(msg); + } + } + + var ERRORS = { + NEXT_WITHOUT_FOR: [0, "Next without for"], + SYNTAX_ERROR: [16, "Syntax error"], + RETURN_WITHOUT_GOSUB: [22, "Return without gosub"], + OUT_OF_DATA: [42, "Out of data"], + ILLEGAL_QUANTITY: [53, "Illegal quantity"], + OVERFLOW: [69, "Overflow"], + OUT_OF_MEMORY: [77, "Out of memory"], + UNDEFINED_STATEMENT: [90, "Undefined statement"], + BAD_SUBSCRIPT: [107, "Bad subscript"], + REDIMED_ARRAY: [120, "Redimensioned array"], + DIVISION_BY_ZERO: [133, "Division by zero"], + TYPE_MISMATCH: [163, "Type mismatch"], + STRING_TOO_LONG: [176, "String too long"], + FORMULA_TOO_COMPLEX: [191, "Formula too complex"], + UNDEFINED_FUNCTION: [224, "Undefined function"], + REENTER: [254, "Re-enter"], + INTERRUPT: [255, "Break"] + }; + + // + // Runtime flow control + // + function EndProgram() { } + function GoToLine(n) { this.line = n; } + function NextLine() { } + function BlockingInput(method, callback) { + this.method = method; + this.callback = callback; + } + + + + // Adapted from: + // http://stackoverflow.com/questions/424292/how-to-create-my-own-javascript-random-number-generator-that-i-can-also-set-the-s + function PRNG() { + var S = 2345678901, // seed + A = 48271, // const + M = 2147483647, // const + Q = M / A, // const + R = M % A; // const + + this.next = function PRNG_next() { + var hi = S / Q, + lo = S % Q, + t = A * lo - R * hi; + S = (t > 0) ? t : t + M; + this.last = S / M; + return this.last; + }; + this.seed = function PRNG_seed(x) { + S = Math.floor(Math.abs(x)); + }; + this.next(); + } + + // Multidimensional array, with auto-dimensioning on first access + function BASICArray(type, dims) { + + var array, dimensions; + + function offset(dims, subscripts) { + if (subscripts.length !== dimensions.length) { + runtime_error(ERRORS.BAD_SUBSCRIPT); + } + + var k, l, s = 0, p, ss; + for (k = 0; k < dims.length; k += 1) { + + ss = subscripts[k]; + if (ss < 0) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + ss = ss >> 0; + if (ss >= dims[k]) { + runtime_error(ERRORS.BAD_SUBSCRIPT); + } + + p = 1; + for (l = k + 1; l < dims.length; l += 1) { + p *= dims[l]; + } + s += p * ss; + } + return s; + } + + this.dim = function dim(dims) { + if (array) { + runtime_error(ERRORS.REDIMED_ARRAY); + } + + dimensions = dims.map(function(n) { return (Number(n) >> 0) + 1; }); + + var i, len = dimensions.reduce(function(a, b) { return a * b; }), + defval = (type === 'string') ? '' : 0; + + array = []; + for (i = 0; i < len; i += 1) { + array[i] = defval; + } + }; + + this.get = function _get(subscripts) { + if (!array) { + this.dim(subscripts.map(function() { return 10; })); + } + + + return array[offset(dimensions, subscripts)]; + }; + + this.set = function _set(subscripts, value) { + if (!array) { + this.dim(subscripts.map(function() { return 10; })); + } + + array[offset(dimensions, subscripts)] = value; + }; + + this.toJSON = function toJSON() { + return { type: type, dimensions: dimensions, array: array }; + }; + + if (dims) { + this.dim(dims); + } + } + + // Stream API, for parsing source and INPUT entry + function Stream(string) { + this.line = 0; + this.column = 0; + + this.match = function match(re) { + var m = string.match(re), lines; + if (m) { + string = string.substring(m[0].length); + lines = m[0].split('\n'); + if (lines.length > 1) { + this.line += lines.length - 1; + this.column = lines[lines.length - 1].length; + } else { + this.column += m[0].length; + } + + this.lastMatch = m; + return m; + } + return (void 0); + }; + + this.eof = function eof() { + return string.length === 0; + }; + } + + // Used for DATA (compile-time) and INPUT (runtime) + // Parses source string for optionally quoted, comma- + // separated values and adds them to items. Returns + // the substring consumed. + var parseDataInput = (function() { + + var regexWhitespace = new RegExp('^[ \\t]+'), + regexQuotedString = new RegExp('^"([^"]*?)"'), + regexUnquotedString = new RegExp('^([^:,\\r\\n]*)'), + regexComma = new RegExp('^,'); + + return function _parseDataInput(stream, items) { + + do { + stream.match(regexWhitespace); + + if (stream.match(regexQuotedString)) { + // quoted string + items.push(stream.lastMatch[1]); + } else if (stream.match(regexUnquotedString)) { + // unquoted string + items.push(stream.lastMatch[1]); + } + } while (stream.match(regexComma)); + }; + } ()); + + + basic.compile = function _compile(source) { + "use strict"; + /*jslint continue: true*/ // for readability + + function vartype(name) { + var s = name.charAt(name.length - 1); + return s === '$' ? 'string' : s === '%' ? 'int' : 'float'; + } + + //---------------------------------------------------------------------- + // + // Runtime Environment (bound to compiled program) + // + //---------------------------------------------------------------------- + + var env, // Environment - passed in to program, contains tty, graphics, etc. + state, // Program state - initialized at runtime + lib, // Statement Library (closure over state and env) + funlib, // Function Library (closure over state and env) + peek_table, // Native memory access shims (PEEK, POKE, CALL) + poke_table, + call_table; + + // + // NOTE: tempting to make these part of env but some access/modify program state, + // e.g. onerr + // + peek_table = { + // Text window + 0x0020: function() { return env.tty.textWindow ? env.tty.textWindow.left : 0; }, + 0x0021: function() { return env.tty.textWindow ? env.tty.textWindow.width : 80; }, + 0x0022: function() { return env.tty.textWindow ? env.tty.textWindow.top : 0; }, + 0x0023: function() { return env.tty.textWindow ? env.tty.textWindow.top + env.tty.textWindow.height : 24; }, + 0x0024: function() { return env.tty.getCursorPosition().x; }, + 0x0025: function() { return env.tty.getCursorPosition().y; }, + + // Random number field + 0x004e: function() { return (Math.random() * 256) & 0xff; }, + 0x004f: function() { return (Math.random() * 256) & 0xff; }, + + // Last error code + 0x00de: function() { return state.onerr_code; }, + + // Hires Plotting Page (32=1, 64=2, 96=3) + 0x00e6: function() { return env.display ? (env.display.hires_plotting_page === 2 ? 64 : 32) : 0; }, + + // TODO: 0x3D0 = 0x4C if DOS is present. + + // Keyboard + 0xC000: function() { return env.tty.getKeyboardRegister ? env.tty.getKeyboardRegister() : 0; }, + 0xC010: function() { return env.tty.clearKeyboardStrobe ? env.tty.clearKeyboardStrobe() : 0; }, + + // Speaker toggle + 0xC030: function() { return 0; }, + + // Buttons + 0xC060: function() { return env.tty.getButtonState ? env.tty.getButtonState(3) : 0; }, + 0xC061: function() { return env.tty.getButtonState ? env.tty.getButtonState(0) : 0; }, + 0xC062: function() { return env.tty.getButtonState ? env.tty.getButtonState(1) : 0; }, + 0xC063: function() { return env.tty.getButtonState ? env.tty.getButtonState(2) : 0; } + }; + + poke_table = { + // Text window + 0x0020: function(v) { if (env.tty.textWindow) { env.tty.textWindow.left = v; } }, + 0x0021: function(v) { if (env.tty.textWindow) { env.tty.textWindow.width = v; } }, + 0x0022: function(v) { if (env.tty.textWindow) { env.tty.textWindow.top = v; } }, + 0x0023: function(v) { if (env.tty.textWindow) { env.tty.textWindow.height = v - env.tty.textWindow.top; } }, + 0x0024: function(v) { env.tty.setCursorPosition(v, void 0); }, + 0x0025: function(v) { env.tty.setCursorPosition(void 0, v); }, + + // ONERR flag + 0x00D8: function(v) { if (v < 0x80) { state.onerr_handler = (void 0); } }, + + // Hires Plotting Page (32=1, 64=2, 96=3) + 0x00E6: function(v) { if (env.display) { env.display.hires_plotting_page = (v === 64 ? 2 : 1); } }, + + // Keyboard strobe + 0xC010: function(v) { unused(v); if (env.tty.clearKeyboardStrobe) { env.tty.clearKeyboardStrobe(); } }, + + // Display switches + 0xC050: function(v) { unused(v); if (env.display) { env.display.setState("graphics", true); } }, // Graphics + 0xC051: function(v) { unused(v); if (env.display) { env.display.setState("graphics", false); } }, // Text + 0xC052: function(v) { unused(v); if (env.display) { env.display.setState("full", true); } }, // Full Graphics + 0xC053: function(v) { unused(v); if (env.display) { env.display.setState("full", false); } }, // Split Screen + 0xC054: function(v) { unused(v); if (env.display) { env.display.setState("page1", true); } }, // Page 1 + 0xC055: function(v) { unused(v); if (env.display) { env.display.setState("page1", false); } }, // Page 2 + 0xC056: function(v) { unused(v); if (env.display) { env.display.setState("lores", true); } }, // Lo-Res + 0xC057: function(v) { unused(v); if (env.display) { env.display.setState("lores", false); } }, // Hi-Res + + // Speaker toggle + 0xC030: function(v) { unused(v); } // no-op + }; + + call_table = { + 0xF3E4: function() { // Reveal hi-res page 1 + if (!env.hires) { runtime_error('Hires graphics not supported'); } + env.display.setState('graphics', true, 'full', true, 'page1', true, 'lores', false); + }, + 0xF3F2: function() { // Clear hi-res screen to black + var hires = env.display.hires_plotting_page === 2 ? env.hires2 : env.hires; + if (!hires) { runtime_error('Hires graphics not supported'); } + hires.clear(); + }, + 0xF3F6: function() { // Clear hi-res screen to last color Hplotted + var hires = env.display.hires_plotting_page === 2 ? env.hires2 : env.hires; + if (!hires) { runtime_error('Hires graphics not supported'); } + hires.clear(hires.color); + }, + 0xD683: function() { // Clear stack + state.stack = []; + }, + 0xFC9C: function() { // Clear from cursor to right + if (env.tty.clearEOL) { env.tty.clearEOL(); } + } + }; + + lib = { + + ////////////////////////////////////////////////////////////////////// + // + // Variable Statements + // + ////////////////////////////////////////////////////////////////////// + + 'clear': function CLEAR() { + state.clear(); + }, + + 'dim': function DIM(name, subscripts) { + state.arrays[name].dim(subscripts); + }, + + 'def': function DEF(name, func) { + state.functions[name] = func; + }, + + ////////////////////////////////////////////////////////////////////// + // + // Flow Control Statements + // + ////////////////////////////////////////////////////////////////////// + + 'goto': function GOTO(line) { + throw new GoToLine(line); + }, + + 'on_goto': function ON_GOTO(index, line1, line2 /* ... */) { + unused(line1, line2); + index = (index - 1) >> 0; + var lines = Array.prototype.slice.call(arguments, 1); + + if (index < 0 || index >= lines.length) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + throw new GoToLine(lines[index]); + }, + + 'gosub': function GOSUB(line) { + state.stack.push({ + gosub_return: state.stmt_index, + line_number: state.line_number + }); + throw new GoToLine(line); + }, + + 'on_gosub': function ON_GOSUB(index, line1, line2 /* ... */) { + unused(line1, line2); + index = (index - 1) >> 0; + var lines = Array.prototype.slice.call(arguments, 1); + if (index < 0 || index >= lines.length) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + state.stack.push({ + gosub_return: state.stmt_index, + line_number: state.line_number + }); + throw new GoToLine(lines[index]); + }, + + 'return': function RETURN() { + var stack_record; + while (state.stack.length) { + stack_record = state.stack.pop(); + if ({}.hasOwnProperty.call(stack_record, 'gosub_return')) { + state.stmt_index = stack_record.gosub_return; + state.line_number = stack_record.line_number; + return; + } + } + runtime_error(ERRORS.RETURN_WITHOUT_GOSUB); + }, + + 'pop': function POP() { + var stack_record; + while (state.stack.length) { + stack_record = state.stack.pop(); + if ({}.hasOwnProperty.call(stack_record, 'gosub_return')) { + return; + } + } + runtime_error(ERRORS.RETURN_WITHOUT_GOSUB); + }, + + 'for': function FOR(varname, from, to, step) { + state.variables[varname] = from; + state.stack.push({ + index: varname, + from: from, + to: to, + step: step, + for_next: state.stmt_index, + line_number: state.line_number + }); + }, + + 'next': function NEXT(var1, var2 /* ... */) { + unused(var1, var2); + + var varnames = Array.prototype.slice.call(arguments), + varname, stack_record, value; + do { + varname = varnames.shift(); + + do { + stack_record = state.stack.pop(); + if (!stack_record || !{}.hasOwnProperty.call(stack_record, 'for_next')) { + runtime_error(ERRORS.NEXT_WITHOUT_FOR); + } + } while (varname !== (void 0) && stack_record.index !== varname); + + value = state.variables[stack_record.index]; + + value = value + stack_record.step; + state.variables[stack_record.index] = value; + + if (!(stack_record.step > 0 && value > stack_record.to) && + !(stack_record.step < 0 && value < stack_record.to) && + !(stack_record.step === 0 && value === stack_record.to)) { + state.stack.push(stack_record); + state.stmt_index = stack_record.for_next; + state.line_number = stack_record.line_number; + return; + } + } while (varnames.length); + }, + + 'if': function IF(value) { + if (!value) { + throw new NextLine(); + } + }, + + 'stop': function STOP() { + runtime_error(ERRORS.INTERRUPT); + }, + + 'end': function END() { + throw new EndProgram(); + }, + + + ////////////////////////////////////////////////////////////////////// + // + // Error Handling Statements + // + ////////////////////////////////////////////////////////////////////// + + 'onerr_goto': function ONERR_GOTO(line) { + state.onerr_handler = line; + }, + + 'resume': function RESUME() { + state.stmt_index = state.resume_stmt_index; + state.line_number = state.resume_line_number; + }, + + ////////////////////////////////////////////////////////////////////// + // + // Inline Data Statements + // + ////////////////////////////////////////////////////////////////////// + + 'restore': function RESTORE() { + state.data_index = 0; + }, + + // PERF: optimize by turning into a function, e.g. "state.parsevar(name, lib.read())" + 'read': function READ(lvalue1, lvalue2 /* ... */) { + unused(lvalue1, lvalue2); + + var lvalues = Array.prototype.slice.call(arguments); + while (lvalues.length) { + if (state.data_index >= state.data.length) { + runtime_error(ERRORS.OUT_OF_DATA); + } + (lvalues.shift())(state.data[state.data_index]); + state.data_index += 1; + } + }, + + ////////////////////////////////////////////////////////////////////// + // + // I/O Statements + // + ////////////////////////////////////////////////////////////////////// + + 'print': function PRINT(string1, string2 /* ... */) { + unused(string1, string2); + + var args = Array.prototype.slice.call(arguments), arg; + while (args.length) { + arg = args.shift(); + if (typeof arg === 'function') { + arg = arg(); + } + env.tty.writeString(String(arg)); + } + }, + + 'comma': function COMMA() { + return function() { + var cur = env.tty.getCursorPosition().x, + pos = (cur + 16) - (cur % 16); + if (pos >= env.tty.getScreenSize().width) { + return '\r'; + } else { + return ' '.repeat(pos - cur); + } + }; + + }, + + 'spc': function SPC(n) { + n = n >> 0; + if (n < 0 || n > 255) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + return function() { + return ' '.repeat(n); + }; + }, + + 'tab': function TAB(n) { + n = n >> 0; + if (n < 0 || n > 255) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + if (n === 0) { n = 256; } + + return function() { + var pos = env.tty.getCursorPosition().x + 1; + return ' '.repeat(pos >= n ? 0 : n - pos); + }; + }, + + 'get': function GET(lvalue) { + var im = env.tty.readChar, + ih = function(entry) { + lvalue(entry); + }; + throw new BlockingInput(im, ih); + }, + + 'input': function INPUT(prompt, var1, var2 /* ... */) { + unused(var1, var2); + var varlist = Array.prototype.slice.call(arguments, 1); // copy for closure + var im, ih; + im = function(cb) { return env.tty.readLine(cb, prompt); }; + ih = function(entry) { + var parts = [], + stream = new Stream(entry); + + parseDataInput(stream, parts); + + while (varlist.length && parts.length) { + try { + varlist.shift()(parts.shift()); + } catch (e) { + if (e instanceof basic.RuntimeError && + e.code === ERRORS.TYPE_MISMATCH[0]) { + e.code = ERRORS.REENTER[0]; + e.message = ERRORS.REENTER[1]; + } + throw e; + } + } + + if (varlist.length) { + prompt = '??'; + throw new BlockingInput(im, ih); + } + + if (parts.length) { + env.tty.writeString('?EXTRA IGNORED\r'); + } + }; + throw new BlockingInput(im, ih); + }, + + 'home': function HOME() { + if (env.tty.clearScreen) { env.tty.clearScreen(); } + }, + + 'htab': function HTAB(pos) { + if (pos < 1 || pos >= env.tty.getScreenSize().width + 1) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + if (env.tty.textWindow) { + pos += env.tty.textWindow.left; + } + + env.tty.setCursorPosition(pos - 1, void 0); + }, + + 'vtab': function VTAB(pos) { + if (pos < 1 || pos >= env.tty.getScreenSize().height + 1) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + env.tty.setCursorPosition(void 0, pos - 1); + }, + + 'inverse': function INVERSE() { + if (env.tty.setTextStyle) { env.tty.setTextStyle(env.tty.TEXT_STYLE_INVERSE); } + }, + 'flash': function FLASH() { + if (env.tty.setTextStyle) { env.tty.setTextStyle(env.tty.TEXT_STYLE_FLASH); } + }, + 'normal': function NORMAL() { + if (env.tty.setTextStyle) { env.tty.setTextStyle(env.tty.TEXT_STYLE_NORMAL); } + }, + 'text': function TEXT() { + if (env.display) { + env.display.setState("graphics", false); + } + + if (env.tty.textWindow) { + // Reset text window + env.tty.textWindow = { + left: 0, + top: 0, + width: env.tty.getScreenSize().width, + height: env.tty.getScreenSize().height + }; + } + }, + + ////////////////////////////////////////////////////////////////////// + // + // Miscellaneous Statements + // + ////////////////////////////////////////////////////////////////////// + + 'notrace': function NOTRACE() { + state.trace_mode = false; + }, + 'trace': function TRACE() { + state.trace_mode = true; + }, + + ////////////////////////////////////////////////////////////////////// + // + // Lores Graphics + // + ////////////////////////////////////////////////////////////////////// + + 'gr': function GR() { + if (!env.lores) { runtime_error('Lores graphics not supported'); } + env.display.setState("lores", true, "full", false, "graphics", true); + env.lores.clear(); + + env.tty.setCursorPosition(0, env.tty.getScreenSize().height); + }, + + 'color': function COLOR(n) { + if (!env.lores) { runtime_error('Lores graphics not supported'); } + + n = n >> 0; + if (n < 0) { runtime_error(ERRORS.ILLEGAL_QUANTITY); } + + env.lores.setColor(n); + }, + + 'plot': function PLOT(x, y) { + if (!env.lores) { runtime_error('Lores graphics not supported'); } + + x = x >> 0; + y = y >> 0; + + var size = env.lores.getScreenSize(); + if (x < 0 || y < 0 || x >= size.width || y >= size.height) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + env.lores.plot(x, y); + }, + + 'hlin': function HLIN(x1, x2, y) { + if (!env.lores) { runtime_error('Lores graphics not supported'); } + + x1 = x1 >> 0; + x2 = x2 >> 0; + y = y >> 0; + + var size = env.lores.getScreenSize(); + if (x1 < 0 || x2 < 0 || y < 0 || + x1 >= size.width || x2 >= size.width || y >= size.height) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + env.lores.hlin(x1, x2, y); + }, + + 'vlin': function VLIN(y1, y2, x) { + if (!env.lores) { runtime_error('Lores graphics not supported'); } + + y1 = y1 >> 0; + y2 = y2 >> 0; + x = x >> 0; + + var size = env.lores.getScreenSize(); + if (x < 0 || y1 < 0 || y2 < 0 || + x >= size.width || y1 >= size.height || y2 >= size.height) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + env.lores.vlin(y1, y2, x); + }, + + + ////////////////////////////////////////////////////////////////////// + // + // Hires Graphics + // + ////////////////////////////////////////////////////////////////////// + + + 'hgr': function HGR() { + if (!env.hires) { runtime_error('Hires graphics not supported'); } + env.display.setState("lores", false, "full", false, "page1", true, "graphics", true); + env.display.hires_plotting_page = 1; + env.hires.clear(); + }, + + 'hgr2': function HGR2() { + if (!env.hires) { runtime_error('Hires graphics not supported'); } + env.display.setState("lores", false, "full", true, "page1", false, "graphics", true); + env.display.hires_plotting_page = 2; + env.hires2.clear(); + }, + + 'hcolor': function HCOLOR(n) { + if (!env.hires) { runtime_error('Hires graphics not supported'); } + n = n >> 0; + if (n < 0 || n > 7) { runtime_error(ERRORS.ILLEGAL_QUANTITY); } + env.hires.setColor(n); + if (env.hires2) { env.hires2.setColor(n); } + }, + + 'hplot': function HPLOT(x1, y1, x2, y2 /* ... */) { + unused(x1, y1, x2, y2); + + var hires = env.display.hires_plotting_page === 2 ? env.hires2 : env.hires; + if (!hires) { runtime_error('Hires graphics not supported'); } + + var coords = Array.prototype.slice.call(arguments), + size = hires.getScreenSize(), + x, y; + + x = coords.shift() >> 0; + y = coords.shift() >> 0; + + if (x < 0 || y < 0 || x >= size.width || y >= size.height) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + hires.plot(x, y); + while (coords.length) { + x = coords.shift() >> 0; + y = coords.shift() >> 0; + if (x < 0 || y < 0 || x >= size.width || y >= size.height) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + hires.plot_to(x, y); + } + }, + + 'hplot_to': function HPLOT_TO(x1, y1, x2, y2 /* ... */) { + unused(x1, y1, x2, y2); + + var hires = env.display.hires_plotting_page === 2 ? env.hires2 : env.hires; + if (!hires) { runtime_error('Hires graphics not supported'); } + + var coords = Array.prototype.slice.call(arguments), + size = hires.getScreenSize(), x, y; + + while (coords.length) { + x = coords.shift() >> 0; + y = coords.shift() >> 0; + + if (x < 0 || y < 0 || x >= size.width || y >= size.height) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + hires.plot_to(x, y); + } + }, + + + ////////////////////////////////////////////////////////////////////// + // + // Compatibility shims + // + ////////////////////////////////////////////////////////////////////// + + 'pr#': function PR(slot) { + if (slot === 0) { + if (env.tty.setFirmwareActive) { env.tty.setFirmwareActive(false); } + } else if (slot === 3) { + if (env.tty.setFirmwareActive) { env.tty.setFirmwareActive(true); } + } + }, + + 'poke': function POKE(address, value) { + address = address & 0xffff; + + value = value >> 0; + if (value < 0 || value > 255) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + if (!({}.hasOwnProperty.call(poke_table, address))) { + runtime_error("Unsupported POKE location: " + address); + } + + poke_table[address](value); + }, + + 'call': function CALL(address) { + address = address & 0xffff; + + if (!({}.hasOwnProperty.call(call_table, address))) { + runtime_error("Unsupported POKE location: " + address); + } + + call_table[address](); + }, + + 'speed': function SPEED(n) { + n = n >> 0; + if (n < 0 || n > 255) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + env.tty.speed = n; + }, + + ////////////////////////////////////////////////////////////////////// + // + // Referenced by compiled functions + // + ////////////////////////////////////////////////////////////////////// + + 'div': function _div(n, d) { + var r = n / d; + if (!isFinite(r)) { runtime_error(ERRORS.DIVISION_BY_ZERO); } + return r; + }, + + 'fn': function _fn(name, arg) { + if (!{}.hasOwnProperty.call(state.functions, name)) { + runtime_error(ERRORS.UNDEFINED_FUNCTION); + } + return state.functions[name](arg); + }, + + 'checkFinite': function _checkFinite(n) { + if (!isFinite(n)) { runtime_error(ERRORS.OVERFLOW); } + return n; + }, + + 'toint': function _toint(n) { + n = n >> 0; + if (n > 0x7fff || n < -0x8000) { runtime_error(ERRORS.ILLEGAL_QUANTITY); } + return n; + } + }; + + // Apply a signature [return_type, arg0_type, arg1_type, ...] to a function + function funcsign(func, return_type, arg0_type, arg1_type /* ... */) { + unused(return_type, arg0_type, arg1_type); + + func.signature = Array.prototype.slice.call(arguments, 1); + return func; + } + + funlib = { + + ////////////////////////////////////////////////////////////////////// + // + // Functions + // + // name: [ impl, returntype, [arg0type [, arg1type [, ... ] ] + // + ////////////////////////////////////////////////////////////////////// + + + "ABS": funcsign(Math.abs, 'number', 'number'), + "ASC": funcsign(function(s) { + if (s.length < 1) { runtime_error(ERRORS.ILLEGAL_QUANTITY); } + return s.charCodeAt(0); + }, 'number', 'string'), + "ATN": funcsign(Math.atan, 'number', 'number'), + "CHR$": funcsign(String.fromCharCode, 'string', 'number'), + "COS": funcsign(Math.cos, 'number', 'number'), + "EXP": funcsign(Math.exp, 'number', 'number'), + "INT": funcsign(Math.floor, 'number', 'number'), + "LEN": funcsign(function LEN(s) { return s.length; }, 'number', 'string'), + "LOG": funcsign(Math.log, 'number', 'number'), + "SGN": funcsign(function SGN(n) { return n > 0 ? 1 : n < 0 ? -1 : 0; }, 'number', 'number'), + "SIN": funcsign(Math.sin, 'number', 'number'), + "SQR": funcsign(Math.sqrt, 'number', 'number'), + "STR$": funcsign(function STR$(n) { return n.toString(); }, 'string', 'number'), + "TAN": funcsign(Math.tan, 'number', 'number'), + "VAL": funcsign(function VAL(s) { + var n = parseFloat(s); + return isFinite(n) ? n : 0; + }, 'number', 'string'), + + "RND": funcsign(function RND(n) { + if (n > 0) { + // Next in PRNG sequence + return state.prng.next(); + } else if (n < 0) { + // Re-seed. NOTE: Not predictable as in Applesoft + state.prng.seed(n); + return state.prng.next(); + } + return state.prng.last; + }, 'number', 'number'), + + "LEFT$": funcsign(function LEFT$(s, n) { return s.substring(0, n); }, 'string', 'string', 'number'), + "MID$": funcsign(function MID$(s, n, n2) { return n2 === (void 0) ? s.substring(n - 1) : s.substring(n - 1, n + n2 - 1); }, 'string', 'string', 'number', 'number?'), + "RIGHT$": funcsign(function RIGHT$(s, n) { return s.length < n ? s : s.substring(s.length - n); }, 'string', 'string', 'number'), + + "POS": funcsign(function POS(n) { unused(n); return env.tty.getCursorPosition().x; }, 'number', 'number'), + "SCRN": funcsign(function SCRN(x, y) { + if (!env.lores) { runtime_error("Graphics not supported"); } + x = x >> 0; + y = y >> 0; + var size = env.lores.getScreenSize(); + if (x < 0 || y < 0 || x >= size.width || y >= size.height) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + return env.lores.getPixel(x, y); + }, 'number', 'number', 'number'), + "HSCRN": funcsign(function HSCRN(x, y) { + var hires = env.display.hires_plotting_page === 2 ? env.hires2 : env.hires; + if (!hires) { runtime_error("Graphics not supported"); } + + x = x >> 0; + y = y >> 0; + var size = hires.getScreenSize(); + if (x < 0 || y < 0 || x >= size.width || y >= size.height) { + runtime_error(ERRORS.ILLEGAL_QUANTITY); + } + + return hires.getPixel(x, y); + }, 'number', 'number', 'number'), + + "PDL": funcsign(function PDL(n) { + if (env.paddle) { + return (env.paddle(n) * 255) & 0xff; + } else { + runtime_error('Paddles not attached'); + } + }, 'number', 'number'), + "FRE": funcsign(function FRE(n) { + unused(n); + return JSON ? JSON.stringify([state.variables, state.arrays, state.functions]).length : 0; + }, 'number', 'number'), + "PEEK": funcsign(function PEEK(address) { + address = address & 0xffff; + if (!{}.hasOwnProperty.call(peek_table, address)) { + runtime_error("Unsupported PEEK location: " + address); + } + return peek_table[address](); + }, 'number', 'number'), + + // Not supported + "USR": funcsign(function USR(n) { unused(n); runtime_error("USR Function not supported"); }, 'number', 'number') + }; + + + //---------------------------------------------------------------------- + // + // Parser / Compiler + // + //---------------------------------------------------------------------- + + var program = (function() { + + var identifiers = { + variables: {}, + arrays: {} + }; + + ////////////////////////////////////////////////////////////////////// + // + // Lexical Analysis + // + ////////////////////////////////////////////////////////////////////// + + var match, test, endOfStatement, endOfProgram, + currLine = 0, currColumn = 0, + currLineNumber = 0; + + function parse_error(msg) { + var e = new basic.ParseError(msg + " in line " + currLineNumber, + currLine, currColumn); + + throw e; + } + + + (function(source) { + function munge(kw) { + // Escape special characters + function escape(c) { return /[\[\]\\\^\$\.\|\?\*\+\(\)]/.test(c) ? '\\' + c : c; } + // Allow linear whitespace between characters + //return kw.split('').map(escape).join('[ \\t]*'); + + // Allow linear whitespace in HCOLOR=, HIMEM:, CHR$, etc + return kw.split(/(?=\W)/).map(escape).join('[ \\t]*'); + } + + var RESERVED_WORDS = [ + // NOTE: keywords that are stems of other words need to go after (e.g. "NOTRACE", "NOT) + "ABS", "AND", "ASC", "ATN", "AT", "CALL", "CHR$", "CLEAR", "COLOR=", "CONT", "COS", + /*"DATA",*/"DEF", "DEL", "DIM", "DRAW", "END", "EXP", "FLASH", "FN", "FOR", "FRE", "GET", + "GOSUB", "GOTO", "GR", "HCOLOR=", "HGR2", "HGR", "HIMEM:", "HLIN", "HOME", "HPLOT", + "HTAB", "IF", "IN#", "INPUT", "INT", "INVERSE", "LEFT$", "LEN", "LET", "LIST", + "LOAD", "LOG", "LOMEM:", "MID$", "NEW", "NEXT", "NORMAL", "NOTRACE", "NOT", "ONERR", + "ON", "OR", "PDL", "PEEK", "PLOT", "POKE", "POP", "POS", "PRINT", "PR#", "READ", + "RECALL", /*"REM",*/"RESTORE", "RESUME", "RETURN", "RIGHT$", "RND", "ROT=", "RUN", + "SAVE", "SCALE=", "SCRN", "SGN", "SHLOAD", "SIN", "SPC", "SPEED=", "SQR", "STEP", + "STOP", "STORE", "STR$", "TAB", "TAN", "TEXT", "THEN", "TO", "TRACE", "USR", "VAL", + "VLIN", "VTAB", "WAIT", "XDRAW", "&", "?", + "HSCRN" + ], + regexReservedWords = new RegExp("^(" + RESERVED_WORDS.map(munge).join("|") + ")", "i"), + regexIdentifier = new RegExp('^([A-Za-z][A-Za-z0-9]?)[A-Za-z0-9]*(\\$|%)?'), + regexStringLiteral = new RegExp('^"([^"]*?)(?:"|(?=\\n|\\r|$))'), + regexNumberLiteral = new RegExp('^([0-9]*\\.?[0-9]+(?:[eE]\\s*[\\-+]?\\s*[0-9]+)?)'), + regexOperator = new RegExp('^(;|<[ \t]*=|=[ \t]*<|>[ \t]*=|=[ \t]*>|=[ \t]*=|<[ \t]*>|>[ \t]*<|=|<|>|\\+|-|\\*|/|\\^|\\(|\\)|,)'), + + regexLineNumber = new RegExp('^([0-9]+)'), + regexSeparator = new RegExp('^(:)'), + + regexRemark = new RegExp('^(' + munge('REM') + '([^\r\n]*))', 'i'), + regexData = new RegExp('^(' + munge('DATA') + ')', 'i'), + + regexLinearWhitespace = new RegExp('^[ \t]+'), + regexNewline = new RegExp('^\r?\n'); + + // Token types: + // lineNumber - start of a new line + // separator - separates statements on same line + // reserved - reserved keyword (command, function, etc) + // identifier - variable name + // string - string literal + // number - number literal + // operator - operator + // remark - REM blah + // data - DATA blah,"blah",blah + + var start = true, + stream = new Stream(source); + + function nextToken() { + var token = {}, newline = start, ws; + start = false; + + currLine = stream.line + 1; + currColumn = stream.column + 1; + + // Consume whitespace + do { + ws = false; + if (stream.match(regexLinearWhitespace)) { + ws = true; + } else if (stream.match(regexNewline)) { + ws = true; + newline = true; + } + } while (ws); + + if (stream.eof()) { + return (void 0); + } + + if (newline) { + if (stream.match(regexLineNumber)) { + token.lineNumber = Number(stream.lastMatch[1]); + } else if (stream.match(regexSeparator)) { + // Extension - allow leading : to continue previous line + token.separator = stream.lastMatch[1]; + } else { + parse_error("Syntax error: Expected line number or separator"); + } + } else if (stream.match(regexRemark)) { + token.remark = stream.lastMatch[2]; + } else if (stream.match(regexData)) { + token.data = []; + parseDataInput(stream, token.data); + } else if (stream.match(regexReservedWords)) { + token.reserved = stream.lastMatch[1].toUpperCase().replace(/\s+/g, ''); + if (token.reserved === "?") { token.reserved = "PRINT"; } // HACK + } else if (stream.match(regexIdentifier)) { + token.identifier = stream.lastMatch[1].toUpperCase() + (stream.lastMatch[2] || ''); // Canonicalize identifier name + } else if (stream.match(regexStringLiteral)) { + token.string = stream.lastMatch[1]; + } else if (stream.match(regexNumberLiteral)) { + token.number = parseFloat(stream.lastMatch[1].replace(/\s+/g, '')); + } else if (stream.match(regexOperator)) { + token.operator = stream.lastMatch[1].replace(/\s+/g, ''); + } else if (stream.match(regexSeparator)) { + token.separator = stream.lastMatch[1]; + } else { + parse_error("Syntax error: Unexpected '" + source.substr(0, 40) + "'"); + } + return token; + } + + var lookahead = nextToken(); + + match = function _match(type, value) { + + if (!lookahead) { + parse_error("Syntax error: Expected " + type + ", saw end of file"); + } + + var token = lookahead; + if ('lineNumber' in token) { + currLineNumber = token.lineNumber; + } + lookahead = nextToken(); + + if (!{}.hasOwnProperty.call(token, type)) { + parse_error("Syntax error: Expected " + type + ", saw " + JSON.stringify(token)); + } + + if (value !== (void 0) && token[type] !== value) { + parse_error("Syntax error: Expected '" + value + "', saw " + JSON.stringify(token)); + } + + return token[type]; + }; + + test = function _test(type, value, consume) { + if (lookahead && {}.hasOwnProperty.call(lookahead, type) && + (value === (void 0) || lookahead[type] === value)) { + + if (consume) { + var token = lookahead; + if ('lineNumber' in token) { + currLineNumber = token.lineNumber; + } + lookahead = nextToken(); + } + + return true; + } + + return false; + }; + + endOfStatement = function _endOfStatement() { + return !lookahead || + {}.hasOwnProperty.call(lookahead, 'separator') || + {}.hasOwnProperty.call(lookahead, 'lineNumber'); + }; + + endOfProgram = function _endOfProgram() { + return !lookahead; + }; + + } (source)); + + + ////////////////////////////////////////////////////////////////////// + // + // Compiler utility functions + // + ////////////////////////////////////////////////////////////////////// + + function quote(string) { + // From json2.js (http://www.json.org/js.html) + var escapable = new RegExp('[\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]', 'g'), + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"': '\\"', + '\\': '\\\\' + }; + + return '"' + string.replace(escapable, function(a) { + var c = meta[a]; + return c ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"'; + } + + + ////////////////////////////////////////////////////////////////////// + // + // Recursive Descent Parser + // + ////////////////////////////////////////////////////////////////////// + + var parseExpression, parseSubscripts; + + // + // Type Checking + // + + function parseAnyExpression() { + var expr = parseExpression(); + return expr.source; + } + + function enforce_type(actual, expected) { + if (actual !== expected) { + parse_error('Type mismatch error: Expected ' + expected); + } + } + + function parseStringExpression() { + var expr = parseExpression(); + enforce_type(expr.type, 'string'); + return expr.source; + } + + function parseNumericExpression() { + var expr = parseExpression(); + enforce_type(expr.type, 'number'); + return expr.source; + } + + // + // Variables + // + + parseSubscripts = function() { + var subscripts; // undefined = no subscripts + + if (test('operator', '(', true)) { + + subscripts = []; + + do { + subscripts.push(parseNumericExpression()); + } while (test('operator', ',', true)); + + match("operator", ")"); + + return subscripts.join(','); + } + return (void 0); + }; + + function parsePValue() { + var name = match('identifier'), + subscripts = parseSubscripts(); + + if (subscripts) { + identifiers.arrays[name] = true; + return '(function (value){state.parsevar(' + + quote(name) + ',[' + subscripts + '],value);})'; + } else { + identifiers.variables[name] = true; + return '(function (value){state.parsevar(' + + quote(name) + ',value);})'; + } + } + + + // + // Expressions + // + + parseExpression = (function() { + // closure to keep things tidy + + function parseUserfunction() { + var name = match('identifier'), + type = vartype(name) === 'string' ? 'string' : 'number', + expr; + + // FUTURE: Allow differing argument type and return type + // (may require runtime type checks) + + // Determine the function argument + match("operator", "("); + expr = type === 'string' ? parseStringExpression() : parseNumericExpression(); + match("operator", ")"); + + return { source: 'lib.fn(' + quote(name) + ',' + expr + ')', type: type }; + } + + + function parsefunction(name) { + if (!{}.hasOwnProperty.call(funlib, name)) { + parse_error("Undefined function: " + name); + } + + match("operator", "("); + + var func = funlib[name], + funcdesc = func.signature.slice(), + rtype = funcdesc.shift(), + args = [], + atype; + + while (funcdesc.length) { + atype = funcdesc.shift(); + + if (/\?$/.test(atype)) { + if (test('operator', ')')) { + break; + } else { + atype = atype.substring(0, atype.length - 1); + } + } + if (args.length) { + match("operator", ","); + } + + if (atype === 'string') { + args.push(parseStringExpression()); + } else if (atype === 'number') { + args.push(parseNumericExpression()); + } else { + throw new Error("Invalid function definition"); + } + } + + match("operator", ")"); + + return { source: 'funlib.' + name + '(' + args.join(',') + ')', type: rtype }; + } + + function parseFinalExpression() { + if (test('number')) { + return { source: String(match('number')), type: 'number' }; + } else if (test('string')) { + return { source: quote(match('string')), type: 'string' }; + } else if (test('reserved', 'FN', true)) { + return parseUserfunction(); + } else if (test('reserved')) { + return parsefunction(match('reserved')); + } else if (test('identifier')) { + var name = match('identifier'), + type = vartype(name) === 'string' ? 'string' : 'number', + subscripts = parseSubscripts(); + if (subscripts) { + identifiers.arrays[name] = true; + return { source: 'state.arrays[' + quote(name) + '].get([' + subscripts + '])', type: type }; + } else { + identifiers.variables[name] = true; + return { source: 'state.variables[' + quote(name) + ']', type: type }; + } + } else { + match("operator", "("); + var expr = parseExpression(); + match("operator", ")"); + return expr; + } + } + + function parseUnaryExpression() { + var rhs, op; + + if (test('operator', '+') || test('operator', '-')) { + op = match('operator'); + } else if (test('reserved', 'NOT')) { + op = match('reserved'); + } + + if (op) { + rhs = parseUnaryExpression(); + + enforce_type(rhs.type, 'number'); + + switch (op) { + case "+": return rhs; + case "-": return { source: '(-' + rhs.source + ')', type: 'number' }; + case "NOT": return { source: '((!' + rhs.source + ')?1:0)', type: 'number' }; + } + } + return parseFinalExpression(); + } + + function parsePowerExpression() { + var lhs = parseUnaryExpression(), rhs; + while (test('operator', '^', true)) { + rhs = parseUnaryExpression(); + + enforce_type(lhs.type, 'number'); + enforce_type(rhs.type, 'number'); + + lhs = { source: 'Math.pow(' + lhs.source + ',' + rhs.source + ')', type: 'number' }; + } + return lhs; + } + + function parseMultiplicativeExpression() { + var lhs = parsePowerExpression(), rhs, op; + while (test('operator', '*') || test('operator', '/')) { + op = match('operator'); + rhs = parsePowerExpression(); + + enforce_type(lhs.type, 'number'); + enforce_type(rhs.type, 'number'); + + switch (op) { + case "*": lhs = { source: '(' + lhs.source + '*' + rhs.source + ')', type: 'number' }; break; + case "/": lhs = { source: 'lib.div(' + lhs.source + ',' + rhs.source + ')', type: 'number' }; break; + } + } + return lhs; + } + + function parseAdditiveExpression() { + var lhs = parseMultiplicativeExpression(), rhs, op; + while (test('operator', '+') || test('operator', '-')) { + op = match('operator'); + rhs = parseMultiplicativeExpression(); + + switch (op) { + case "+": + enforce_type(rhs.type, lhs.type); + lhs = { source: '(' + lhs.source + '+' + rhs.source + ')', type: lhs.type }; break; + case "-": + enforce_type(lhs.type, 'number'); + enforce_type(rhs.type, 'number'); + lhs = { source: '(' + lhs.source + '-' + rhs.source + ')', type: lhs.type }; break; + } + } + return lhs; + } + + function parseRelationalExpression() { + var lhs = parseAdditiveExpression(), rhs, op; + while ( + test('operator', '<') || test('operator', '>') || + test('operator', '=') || test('operator', '==') || + test('operator', '<=') || test('operator', '=<') || + test('operator', '>=') || test('operator', '=>') || + test('operator', '<>') || test('operator', '><')) { + + op = match('operator'); + + rhs = parseAdditiveExpression(); + + enforce_type(rhs.type, lhs.type); + + switch (op) { + case "<": lhs = { source: '((' + lhs.source + '<' + rhs.source + ')?1:0)', type: 'number' }; break; + case ">": lhs = { source: '((' + lhs.source + '>' + rhs.source + ')?1:0)', type: 'number' }; break; + case "<=": + case "=<": lhs = { source: '((' + lhs.source + '<=' + rhs.source + ')?1:0)', type: 'number' }; break; + case ">=": + case "=>": lhs = { source: '((' + lhs.source + '>=' + rhs.source + ')?1:0)', type: 'number' }; break; + case "=": + case "==": lhs = { source: '((' + lhs.source + '===' + rhs.source + ')?1:0)', type: 'number' }; break; + case "<>": + case "><": lhs = { source: '((' + lhs.source + '!==' + rhs.source + ')?1:0)', type: 'number' }; break; + } + } + return lhs; + } + + function parseAndExpression() { + var lhs = parseRelationalExpression(), rhs; + while (test('reserved', 'AND', true)) { + rhs = parseRelationalExpression(); + + enforce_type(lhs.type, 'number'); + enforce_type(rhs.type, 'number'); + + lhs = { + source: '((' + lhs.source + '&&' + rhs.source + ')?1:0)', + type: 'number' + }; + } + return lhs; + } + + function parseOrExpression() { + var lhs = parseAndExpression(), rhs; + while (test('reserved', 'OR', true)) { + rhs = parseAndExpression(); + + enforce_type(lhs.type, 'number'); + enforce_type(rhs.type, 'number'); + + lhs = { + source: '((' + lhs.source + '||' + rhs.source + ')?1:0)', + type: 'number' + }; + } + return lhs; + } + + return parseOrExpression; + } ()); + + + // + // Statements + // + + function parseCommand() { + + function slib(name, arg0, arg1 /* ... */) { + unused(arg0, arg1); + var args = Array.prototype.slice.call(arguments, 1); + return 'lib[' + quote(name) + '](' + args.join(',') + ');'; + } + + var keyword = test('identifier') ? 'LET' : match('reserved'), + name, type, subscripts, is_to, expr, param, args, prompt, trailing, js; + + switch (keyword) { + ////////////////////////////////////////////////////////////////////// + // + // Variable Statements + // + ////////////////////////////////////////////////////////////////////// + + case "CLEAR": // Clear all variables + return slib('clear'); + + case "LET": // Assign a variable, LET x = expr + name = match('identifier'); + subscripts = parseSubscripts(); + match('operator', '='); + + type = vartype(name); + if (type === 'int') { + expr = 'lib.toint(lib.checkFinite(' + parseNumericExpression() + '))'; + } else if (type === 'float') { + expr = 'lib.checkFinite(' + parseNumericExpression() + ')'; + } else { // type === 'string') + expr = parseStringExpression(); + } + + if (!subscripts) { + identifiers.variables[name] = true; + return 'state.variables[' + quote(name) + '] = ' + expr; + } else { + identifiers.arrays[name] = true; + return 'state.arrays[' + quote(name) + '].set([' + subscripts + '], ' + expr + ')'; + } + + case "DIM": + js = ''; + do { + name = match('identifier'); + subscripts = parseSubscripts(); + identifiers.arrays[name] = true; + js += slib('dim', quote(name), '[' + subscripts + ']'); + } while (test('operator', ',', true)); + return js; + + case "DEF": // DEF FN A(X) = expr + match("reserved", "FN"); + name = match('identifier'); + match("operator", "("); + param = match('identifier'); + match("operator", ")"); + match("operator", "="); + + if (vartype(name) !== vartype(param)) { + parse_error("DEF FN function type and argument type must match"); + } + + expr = vartype(name) === 'string' + ? parseStringExpression() + : parseNumericExpression(); + + return slib('def', quote(name), + 'function (arg){' + + // Save the current context/variable so we can evaluate + 'var rv,ov=state.variables[' + quote(param) + '];' + + // Swap in the argument + 'state.variables[' + quote(param) + ']=arg;' + + // Evaluate the user-function expression + 'rv=' + expr + ';' + + // Restore + 'state.variables[' + quote(param) + ']=ov;' + + 'return rv;' + + '}'); + + ////////////////////////////////////////////////////////////////////// + // + // Flow Control Statements + // + ////////////////////////////////////////////////////////////////////// + + case "GOTO": // GOTO linenum + return slib('goto', match("number")); + + case "ON": // ON expr (GOTO|GOSUB) linenum[,linenum ... ] + expr = parseNumericExpression(); + + keyword = match('reserved'); + if (keyword !== "GOTO" && keyword !== "GOSUB") { + parse_error("Syntax error: Expected GOTO or GOSUB"); + } + + args = []; + do { + args.push(match("number")); + } while (test("operator", ",", true)); + + return slib(keyword === 'GOSUB' ? 'on_gosub' : 'on_goto', expr, args.join(',')); + + case "GOSUB": // GOSUB linenum + return slib('gosub', match("number")); + + case "RETURN": // Return from the last GOSUB + return slib('return'); + + case "POP": // Turn last GOSUB into a GOTO + return slib('pop'); + + case "FOR": // FOR i = m TO n STEP s + name = match('identifier'); + if (vartype(name) !== 'float') { + parse_error("Syntax error: Expected floating point variable"); + } + identifiers.variables[name] = true; + + return slib('for', + quote(name), + match("operator", "=") && parseNumericExpression(), + match("reserved", "TO") && parseNumericExpression(), + test('reserved', 'STEP', true) ? parseNumericExpression() : '1'); + + case "NEXT": // NEXT [i [,j ... ] ] + args = []; + if (test('identifier')) { + args.push(quote(match('identifier'))); + while (test("operator", ",", true)) { + args.push(quote(match('identifier'))); + } + } + + return slib('next', args.join(',')); + + case "IF": // IF expr (GOTO linenum|THEN linenum|THEN statement [:statement ... ] + expr = parseAnyExpression(); + + js = slib('if', expr); + + if (test('reserved', 'GOTO', true)) { + // IF expr GOTO linenum + return js + slib('goto', match('number')); + } + + match('reserved', 'THEN'); + if (test('number')) { + // IF expr THEN linenum + return js + slib('goto', match('number')); + } else { + // IF expr THEN statement + return js + parseCommand(); // recurse + } + + case "END": // End program + return slib('end'); + + case "STOP": // Break, like an error + return slib('stop'); + + ////////////////////////////////////////////////////////////////////// + // + // Error Handling Statements + // + ////////////////////////////////////////////////////////////////////// + + case "ONERR": // ONERR GOTO linenum + return slib('onerr_goto', + match("reserved", "GOTO") && match("number")); + + case "RESUME": + return slib('resume'); + + ////////////////////////////////////////////////////////////////////// + // + // Inline Data Statements + // + ////////////////////////////////////////////////////////////////////// + + case "RESTORE": + return slib('restore'); + + case "READ": + args = []; + do { + args.push(parsePValue()); + } while (test("operator", ",", true)); + + return slib('read', args.join(',')); + + ////////////////////////////////////////////////////////////////////// + // + // I/O Statements + // + ////////////////////////////////////////////////////////////////////// + + case "PRINT": // Output to the screen + args = []; + trailing = true; + while (!endOfStatement()) { + if (test('operator', ';', true)) { + trailing = false; + } else if (test('operator', ',', true)) { + trailing = false; + args.push('lib.comma()'); + } else if (test('reserved', 'SPC') || test('reserved', 'TAB')) { + trailing = true; + keyword = match('reserved'); + match("operator", "("); + expr = parseNumericExpression(); + match("operator", ")"); + + args.push('lib.' + (keyword === 'SPC' ? 'spc' : 'tab') + '(' + expr + ')'); + } else { + trailing = true; + args.push(parseAnyExpression()); + } + } + if (trailing) { + args.push(quote('\r')); + } + + return slib('print', args.join(',')); + + case "INPUT": // Read input from keyboard + prompt = '?'; + if (test('string')) { + prompt = match('string'); + match("operator", ";"); + } + + args = []; + + do { + args.push(parsePValue()); + } while (test("operator", ",", true)); + + return slib('input', quote(prompt), args.join(',')); + + case "GET": // Read character from keyboard + return slib('get', parsePValue()); + + case "HOME": // Clear text screen + return slib('home'); + + case "HTAB": // Set horizontal cursor position + return slib('htab', parseNumericExpression()); + + case "VTAB": // Set vertical cursor position + return slib('vtab', parseNumericExpression()); + + case "INVERSE": // Inverse text + return slib('inverse'); + + case "FLASH": // Flashing text + return slib('flash'); + + case "NORMAL": // Normal text + return slib('normal'); + + case "TEXT": // Set display mode to text + return slib('text'); + + ////////////////////////////////////////////////////////////////////// + // + // Miscellaneous Statements + // + ////////////////////////////////////////////////////////////////////// + + case "NOTRACE": // Turn off line tracing + return slib('notrace'); + + case "TRACE": // Turn on line tracing + return slib('trace'); + + ////////////////////////////////////////////////////////////////////// + // + // Lores Graphics + // + ////////////////////////////////////////////////////////////////////// + + case "GR": // Set display mode to lores graphics, clear screen + return slib('gr'); + + case "COLOR=": // Set lores color + return slib('color', parseNumericExpression()); + + case "PLOT": // Plot lores point + return slib('plot', + parseNumericExpression(), + match("operator", ",") && parseNumericExpression()); + + case "HLIN": // Draw lores horizontal line + return slib('hlin', + parseNumericExpression(), + match("operator", ",") && parseNumericExpression(), + match("reserved", "AT") && parseNumericExpression()); + + case "VLIN": // Draw lores vertical line + return slib('vlin', + parseNumericExpression(), + match("operator", ",") && parseNumericExpression(), + match("reserved", "AT") && parseNumericExpression()); + + ////////////////////////////////////////////////////////////////////// + // + // Hires Graphics + // + ////////////////////////////////////////////////////////////////////// + + // Hires Display Routines + case "HGR": // Set display mode to hires graphics, clear screen + return slib('hgr'); + + case "HGR2": // Set display mode to hires graphics, page 2, clear screen + return slib('hgr2'); + + case "HCOLOR=": // Set hires color + return slib('hcolor', parseNumericExpression()); + + case "HPLOT": // Draw hires line + is_to = test('reserved', 'TO', true); + + args = []; + do { + args.push(parseNumericExpression()); + match("operator", ","); + args.push(parseNumericExpression()); + } while (test('reserved', 'TO', true)); + + return slib(is_to ? 'hplot_to' : 'hplot', args.join(',')); + + ////////////////////////////////////////////////////////////////////// + // + // Compatibility shims + // + ////////////////////////////////////////////////////////////////////// + + case "PR#": // Direct output to slot + return slib('pr#', parseNumericExpression()); + + case "CALL": // Call native routine + return slib('call', parseNumericExpression()); + + case "POKE": // Set memory value + return slib('poke', + parseNumericExpression(), + match("operator", ",") && parseNumericExpression()); + + case "SPEED=": // Output speed + return slib('speed', parseNumericExpression()); + + ////////////////////////////////////////////////////////////////////// + // + // INTROSPECTION + // + ////////////////////////////////////////////////////////////////////// + + case "LIST": // List program statements + parse_error("Introspection statement not supported: " + keyword); + return; + + ////////////////////////////////////////////////////////////////////// + // + // Statements that will never be implemented + // + ////////////////////////////////////////////////////////////////////// + + // Shape tables + case "ROT=": // Set rotation angle for hires shape + case "SCALE=": // Set rotation angle for hires shape + case "DRAW": // Draw hires shape + case "XDRAW": // XOR draw hires shape + parse_error("Display statement not supported: " + keyword); + return; + + // Interpreter Routines + case "CONT": // Continue stopped program (immediate mode) + case "DEL": // Deletes program statements + case "NEW": // Wipe program + case "RUN": // Execute program + parse_error("Interpreter statement not supported: " + keyword); + return; + + // Native Routines + case "HIMEM:": // Set upper bound of variable memory + case "IN#": // Direct input from slot + case "LOMEM:": // Set low bound of variable memory + case "WAIT": // Wait for memory value to match a condition + case "&": // Command hook + parse_error("Native interop statement not supported: " + keyword); + return; + + // Tape Routines + case "LOAD": // Load program from cassette port + case "RECALL": // Load array from cassette port + case "SAVE": // Save program to cassette port + case "STORE": // Store array to cassette port + case "SHLOAD": // Load shape table from cassette port + parse_error("Tape statement not supported: " + keyword); + return; + + ////////////////////////////////////////////////////////////////////// + // + // NYI Statements + // + ////////////////////////////////////////////////////////////////////// + + // Parts of other statements - AT, FN, STEP, TO, THEN, etc. + default: + parse_error("Syntax error: " + keyword); + return; + } + } + + // + // Top-level Program Structure + // + + var parseProgram = function() { + + var program = { + statements: [], // array of: [ line-number | statement-function ] + data: [], // array of [ string | number ] + jump: [] // map of: { line-number: statement-index } + }; + + function mkfun(js) { + /*jslint evil:true*/ + var fun; // NOTE: for IE; would prefer Function() + eval('fun = (function (){' + js + '});'); + return fun; + } + + function empty_statement() { } + + // Statement = data-declaration | remark | Command | EmptyStatement + // Command = identifier /*...*/ | reserved /*...*/ + function parseStatement() { + if (test('data')) { + program.data = program.data.concat(match('data')); + return; + } else if (test('remark', void 0, true)) { + return; + } else if (test('reserved') || test('identifier')) { + program.statements.push(mkfun(parseCommand())); + } else { + // So TRACE output is correct + program.statements.push(empty_statement); + } + } + + // Line = line-number Statement { separator Statement } + function parseLine() { + program.statements.push(match('lineNumber')); + parseStatement(); + while (test('separator', ':', true)) { + parseStatement(); + } + } + + // Program = Line { Line } + while (!endOfProgram()) { + parseLine(); + } + + // Produce jump table + program.statements.forEach(function(stmt, index) { + if (typeof stmt === 'number') { + program.jump[stmt] = index; + } + }); + + program.variable_identifiers = Object.keys(identifiers.variables); + program.array_identifiers = Object.keys(identifiers.arrays); + + return program; + }; + + return parseProgram(); + } ()); + + program.init = function _init(environment) { + + // stuff these into runtime library closure/binding + env = environment; + state = { + variables: {}, + arrays: {}, + functions: {}, + data: this.data, + data_index: 0, + stmt_index: 0, + line_number: 0, + stack: [], + prng: new PRNG(), + + onerr_code: 255, + onerr_handler: void 0, + resume_stmt_index: 0, + resume_line_number: 0, + trace_mode: false, + + input_continuation: null, + + clear: function() { + program.variable_identifiers.forEach(function(identifier) { + state.variables[identifier] = vartype(identifier) === 'string' ? '' : 0; + }); + + program.array_identifiers.forEach(function(identifier) { + state.arrays[identifier] = new BASICArray(vartype(identifier)); + }); + + state.functions = {}; + state.data_index = 0; + } + }; + + state.clear(); + + state.parsevar = function _parsevar(name, subscripts, input) { + + if (arguments.length === 2) { + input = arguments[1]; + subscripts = void 0; + } + var value; + + switch (vartype(name)) { + case 'string': + value = input; + break; + + case 'int': + value = Number(input); + if (!isFinite(value)) { runtime_error(ERRORS.TYPE_MISMATCH); } + value = lib.toint(value); + break; + + case 'float': + value = Number(input); + if (!isFinite(value)) { runtime_error(ERRORS.TYPE_MISMATCH); } + break; + } + + if (subscripts) { + state.arrays[name].set(subscripts, value); + } else { + state.variables[name] = value; + } + }; + }; + + program.step = function _step(driver) { + + function gotoline(line) { + if (!{}.hasOwnProperty.call(program.jump, line)) { + runtime_error(ERRORS.UNDEFINED_STATEMENT); + } + state.stmt_index = program.jump[line]; + } + + var stmt; + + try { + // for RuntimeError + + try { + if (state.input_continuation) { + var cont = state.input_continuation; + state.input_continuation = null; + cont(state.input_buffer); + } else if (state.stmt_index >= program.statements.length) { + return basic.STATE_STOPPED; + } else { + + stmt = program.statements[state.stmt_index]; + + if (typeof stmt === 'number') { + state.line_number = stmt; + } else if (typeof stmt === 'function') { + if (state.trace_mode) { + env.tty.writeString('#' + state.line_number + ' '); + } + stmt(); + } else { + throw "WTF?"; + } + } + + state.stmt_index += 1; + return basic.STATE_RUNNING; + + } catch (e) { + // These may throw RuntimeError + if (e instanceof basic.RuntimeError) { + throw e; // let outer catch block handle it + } else if (e instanceof GoToLine) { + gotoline(e.line); + return basic.STATE_RUNNING; + } else if (e instanceof NextLine) { + while (state.stmt_index < program.statements.length && + typeof program.statements[state.stmt_index] !== 'number') { + state.stmt_index += 1; + } + return basic.STATE_RUNNING; + } else if (e instanceof BlockingInput) { + // what to call on next step() after input is handled + state.input_continuation = e.callback; + + // call input method to prepare async input + e.method(function(v) { + state.input_buffer = v; + if (driver) { driver(); } + }); + + return basic.STATE_BLOCKED; + } else if (e instanceof EndProgram) { + return basic.STATE_STOPPED; + } else if (e instanceof Error && /stack|recursion/i.test(e.message)) { + // IE: Error "Out of stack space" + // Firefox: InternalError "too much recursion" + // Safari: RangeError "Maximum call stack size exceeded" + // Chrome: RangeError "Maximum call stack size exceeded" + // Opera: Error "Maximum recursion depth exceeded" + runtime_error(ERRORS.FORMULA_TOO_COMPLEX); + } else if (e instanceof Error && /memory|overflow/i.test(e.message)) { + // IE: Error "Out of memory" + // Firefox: InternalError "allocation size overflow" + // Safari: Error "Out of memory" + // Chrome: (not catchable) + // Opera: (not catchable) + runtime_error(ERRORS.OUT_OF_MEMORY); + // NOTE: not reliably generated; don't unit test + } else { + throw e; + } + } + } catch (rte) { + if (rte instanceof basic.RuntimeError) { + state.onerr_code = rte.code || 0; + if (state.onerr_handler !== void 0) { + state.resume_stmt_index = state.stmt_index; + state.resume_line_number = state.line_number; + gotoline(state.onerr_handler); + return basic.STATE_RUNNING; + } else if (rte.code === ERRORS.REENTER[0]) { + env.tty.writeString('?REENTER\r'); + return basic.STATE_RUNNING; + } else { + // annotate and report to the user + rte.message += " in line " + state.line_number; + throw rte; + } + } else { + throw rte; + } + } + }; + + return program; + }; + + return basic; + +} ()); + + +// TODO: Unit tests for compile errors + +// Console: +// For rhino: rhino basic.js your_basic_program.txt +// For CScript: CScript basic.js your_basic_program.txt + +// TODO: DOS implementation + +if (!window) { + (function() { + /*jslint windows: true, rhino: true */ + + var console, program, state, filename, source; + + if (typeof WScript === 'object') { + + // Microsoft Windows Scripting engine + + if (WScript.Arguments.length !== 1) { + WScript.StdOut.WriteLine("Usage: cscript basic.js program_name"); + WScript.Quit(-1); + } + filename = WScript.Arguments(0); + + source = (function() { + var code = '', + fso = new ActiveXObject("Scripting.FileSystemObject"), + stream = fso.OpenTextFile(filename); + while (!stream.AtEndOfStream) { + code += stream.ReadLine() + '\n'; + } + stream.Close(); + return code; + } ()); + + console = { + gets: function() { return WScript.StdIn.ReadLine(); }, + getc: function() { return WScript.StdIn.ReadLine().substring(0, 1); }, + puts: function(s) { WScript.StdOut.Write(s); }, + putc: function(c) { WScript.StdOut.Write(c); }, + errs: function(s) { WScript.StdErr.Write(s); }, + quit: function(s) { WScript.Quit(s); } + }; + } else if (typeof java === 'object') { + + // Mozilla Rhino + + if (arguments.length !== 1) { + java.lang.System.err.println("Usage: rhino basic.js program_name"); + quit(1); + } + filename = arguments[0]; + + source = (function() { + var r = new java.io.BufferedReader(new java.io.FileReader(new java.io.File(filename))), + sb = new java.lang.StringBuilder(), + s; + + do { + s = r.readLine(); + if (s !== null) { + sb.append(s).append('\n'); + } + } while (s !== null); + return String(sb); + } ()); + + (function() { + var stdin = new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.System['in'])); + + console = { + gets: function() { return String(stdin.readLine()); }, + getc: function() { return String(stdin.readLine()).substring(0, 1); }, + puts: function(s) { java.lang.System.out.print(s); }, + putc: function(c) { java.lang.System.out.print(c); }, + errs: function(s) { java.lang.System.err.print(s); }, + quit: function(s) { quit(s); } + }; + } ()); + } else { + throw 'Unknown script host'; + } + + + // Compile + console.puts('Compiling...\n'); + try { + program = basic.compile(source); + } catch (pe) { + if (pe instanceof basic.ParseError) { + console.errs(pe.message + ' (source line: ' + pe.line + ', column: ' + pe.column + ')\n'); + console.quit(1); + } else { + throw pe; + } + } + + // Run + console.puts('Running...\n'); + program.init({ + tty: { + getCursorPosition: function() { return { x: 0, y: 0 }; }, + setCursorPosition: function() { }, + getScreenSize: function() { return { width: 80, height: 24 }; }, + writeChar: function(ch) { console.putc(ch.replace(/\r/g, '\n')); }, + writeString: function(string) { console.puts(string.replace(/\r/g, '\n')); }, + readChar: function(callback) { + callback(console.getc()); + }, + readLine: function(callback, prompt) { + console.puts(prompt); + callback(console.gets().replace(/[\r\n]*/, '')); + } + } + }); + + try { + do { + state = program.step(); + } while (state !== basic.STATE_STOPPED); + } catch (rte) { + if (rte instanceof basic.RuntimeError) { + console.errs(rte.message + '\n'); + console.quit(1); + } else { + throw rte; + } + } + } ()); +} + + diff --git a/bell.js b/bell.js new file mode 100644 index 0000000..04939e6 --- /dev/null +++ b/bell.js @@ -0,0 +1,55 @@ +// +// Applesoft BASIC in Javascript +// Bell - play an audio file for the CHR$(7) "BEL" beep +// + +// Copyright (C) 2009-2011 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var Bell; +if (typeof Bell !== 'function') { + Bell = function(base) { + + var tag; + + // Prefer HTML5 audio + tag = document.createElement('audio'); + if (typeof tag.canPlayType === 'function') { + tag.setAttribute('preload', 'true'); + if (tag.canPlayType('audio/mp3')) { + tag.setAttribute('src', base + 'bell.mp3'); + } else if (tag.canPlayType('audio/ogg')) { + tag.setAttribute('src', base + 'bell.ogg'); + } else if (tag.canPlayType('audio/wav')) { + tag.setAttribute('src', base + 'bell.wav'); + } + this.play = function() { tag.play(); }; + this.stop = function() { tag.pause(); tag.currentTime = 0; }; + return; + } + + // Fallback for IE<9 + tag = document.createElement('bgsound'); + if ('loop' in tag) { + tag.src = base + 'bell.wav'; + tag.loop = 1; + this.play = function() { document.body.appendChild(tag); }; + this.stop = function() { document.body.removeChild(tag); }; + return; + } + + this.play = function() { }; + this.stop = function() { }; + }; +} diff --git a/bell.mp3 b/bell.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4fc7ecf6d4ff66b342aa8b5ce28af032132e0999 GIT binary patch literal 1880 zcmd7P`#;nB0|)TWY-1RPi6bX-Etg_!v{R9g!_*g3(k+{_4DiX!}IY1n|@sogsS=>yg?Vz776gq zR(?wUIgmNT)`@ZIfZPna@%LegiK$C(O>vxWs3;7C!LfUajSG35%b;^P#kgxq>T*wR z>^jB5q2RNvX?P8n=1|CZ3u2N-qMqt3rLiHK5nN7LvecPYWQ+wb_ zY&cF`l_*eze^^N+$Mu?Bs*WZoQ4!p2imV4KlsAZK43*>6bOF_mvm;I ziwvuq%L zUs|vr2|G9MC`eozJlm@`6A=nEBit=sxu*THvbg@bCVMVz!Gn=k0wsCbsDX4Bgi${IQs_Yk9xq7 zh#sdUOwO#JsNV@%h99j1UlF;dwm@i>8tGzuIe{`jcc2rIS^~-l^8Q|(5E*Izy6Ekk zF#xMNK@@R`1i3rMytdA@LFv(avLAd;{+idi+;6~?bzl&Z3+xrY?U`%nO=6VaW zul%5w{8b1Oe8PiOUDw4EI~6ss_-q?c zzb>&B(f%`3UvXhMH0}+Anmc>BH7+3Bw+F%m>Q(TB>|OsKG3NBy$%Dc0^bgwB?($in zVK;sXNS`ugz5i1*gvhL~!lMn#zAS7q+Znc5A1!rQ3BpHLGn{QuI^H+p-+5Tk2}(4j z90x^uqIt4Ml8@J;^VMMwQUZX1)a#9`@8hQG>7QHlpAsfSqK0`T%e9Clc>~ zui+&~@06{Fa8P#a+4#zae~OIq#3Rb4-6?v5z$ z-OX#YqPfA+xVII9j6oG%u<*3Z+{JJS-;ET1vz`A8+iLMdpr5aDqV)KeQTHMfeBru$ z`n_S}@PVUEE_COpOW7V4w;yt>%&IS4CGahN-{pEUX}v%4+jY~G=fO#}xNTlzuJLy% zsJqDMr!Vi2!=s_FhYv$C;KPGG){ER=x6H55ceSd?J*?$Z6Uz?V4m~E8l4^ zyD;#I7WeMwG{=GhiAYS_mR7A_sraJ+#Lv0-j9ac?Gha&-ixG6qrgiY!Ay;>rj+!=FP^>_og$U14_Q`RAxY)8w2dsj}dd3d+h7RU%v zJKr20NP{pNH|*CDrtSgW@G(kH=(K5b3MIAVku1}8VIU>x^7S!MNgJjJcl;ev6~VzT zOCe=J9x?V|sBcJ?&Q<1$MPTNCcU`pRPfE?IPS3tkBQusp zG!NpMqUu6n8He;|jIR$jJ=VzKPjPj0zeNO_U~lvu#|m|JQ`9Zk{;dAxABB_hdSACA mo{oD+d-ph0|E+9+?9;ok;oBczS@sY_U_lV#Z!Q0!r9T06JIr4I literal 0 HcmV?d00001 diff --git a/bell.ogg b/bell.ogg new file mode 100644 index 0000000000000000000000000000000000000000..a947cb81d4f5f92e6ec51c128eb807c4ecb3031d GIT binary patch literal 4844 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 !SAx%RVfoJT#xQGmWT1LrSD$L%`-Y$f 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 literal 0 HcmV?d00001 diff --git a/cm2/mode/basic/basic.css b/cm2/mode/basic/basic.css new file mode 100644 index 0000000..a8c786e --- /dev/null +++ b/cm2/mode/basic/basic.css @@ -0,0 +1,46 @@ +.cm-s-default span.cm-basic-statement { + color: #00007f; +} + +.cm-s-default span.cm-basic-unsupported { + color: #00007f; + background-color: #ff7f7f +} + +.cm-s-default span.cm-basic-function { + color: teal; +} + +.cm-s-default span.cm-basic-identifier { + color: #7f7f00; +} + +.cm-s-default span.cm-basic-string { + color: #007f00; +} + +.cm-s-default span.cm-basic-number { + color: #0000ff; +} + +.cm-s-default span.cm-basic-operator { + color: #7f007f; +} + +.cm-s-default span.cm-basic-separator { + color: #7f7f7f; +} + +.cm-s-default span.cm-basic-linenumber { + color: orange; +} + +.cm-s-default span.cm-basic-comment { + color: #cc00ff; + font-style: italic; +} + +.cm-s-default span.cm-basic-error { + color: black; + background-color: red; +} diff --git a/cm2/mode/basic/basic.js b/cm2/mode/basic/basic.js new file mode 100644 index 0000000..a84136c --- /dev/null +++ b/cm2/mode/basic/basic.js @@ -0,0 +1,222 @@ + +// Really just a lexer + +CodeMirror.defineMode('basic', function(config, parserConfig) { + + var STATEMENT = 'basic-statement', + OPERATOR = 'basic-operator', + FUNCTION = 'basic-function', + UNSUPPORTED = 'basic-unsupported'; + + var reserved = { + "ABS": FUNCTION, + "AND": OPERATOR, + "ASC": FUNCTION, + "ATN": FUNCTION, + "AT": STATEMENT, + "CALL": STATEMENT, + "CHR$": FUNCTION, + "CLEAR": STATEMENT, + "COLOR=": STATEMENT, + "CONT": UNSUPPORTED, + "COS": FUNCTION, + "DATA": STATEMENT, + "DEF": STATEMENT, + "DEL": UNSUPPORTED, + "DIM": STATEMENT, + "DRAW": UNSUPPORTED, + "END": STATEMENT, + "EXP": FUNCTION, + "FLASH": STATEMENT, + "FN": STATEMENT, + "FOR": STATEMENT, + "FRE": FUNCTION, + "GET": STATEMENT, + "GOSUB": STATEMENT, + "GOTO": STATEMENT, + "GR": STATEMENT, + "HCOLOR=": STATEMENT, + "HGR2": STATEMENT, + "HGR": STATEMENT, + "HIMEM:": UNSUPPORTED, + "HLIN": STATEMENT, + "HOME": STATEMENT, + "HPLOT": STATEMENT, + "HTAB": STATEMENT, + "IF": STATEMENT, + "IN#": UNSUPPORTED, + "INPUT": STATEMENT, + "INT": FUNCTION, + "INVERSE": STATEMENT, + "LEFT$": FUNCTION, + "LEN": FUNCTION, + "LET": STATEMENT, + "LIST": UNSUPPORTED, + "LOAD": UNSUPPORTED, + "LOG": FUNCTION, + "LOMEM:": UNSUPPORTED, + "MID$": FUNCTION, + "NEW": UNSUPPORTED, + "NEXT": STATEMENT, + "NORMAL": STATEMENT, + "NOTRACE": STATEMENT, + "NOT": OPERATOR, + "ONERR": STATEMENT, + "ON": STATEMENT, + "OR": OPERATOR, + "PDL": FUNCTION, + "PEEK": FUNCTION, + "PLOT": STATEMENT, + "POKE": STATEMENT, + "POP": STATEMENT, + "POS": FUNCTION, + "PRINT": STATEMENT, + "PR#": STATEMENT, + "READ": STATEMENT, + "RECALL": UNSUPPORTED, + "REM": STATEMENT, + "RESTORE": STATEMENT, + "RESUME": STATEMENT, + "RETURN": STATEMENT, + "RIGHT$": FUNCTION, + "RND": FUNCTION, + "ROT=": UNSUPPORTED, + "RUN": UNSUPPORTED, + "SAVE": UNSUPPORTED, + "SCALE=": UNSUPPORTED, + "SCRN": FUNCTION, + "SGN": FUNCTION, + "SHLOAD": UNSUPPORTED, + "SIN": FUNCTION, + "SPC": FUNCTION, + "SPEED=": STATEMENT, + "SQR": FUNCTION, + "STEP": STATEMENT, + "STOP": STATEMENT, + "STORE": UNSUPPORTED, + "STR$": FUNCTION, + "TAB": FUNCTION, + "TAN": FUNCTION, + "TEXT": STATEMENT, + "THEN": STATEMENT, + "TO": STATEMENT, + "TRACE": STATEMENT, + "USR": FUNCTION, + "VAL": FUNCTION, + "VLIN": STATEMENT, + "VTAB": STATEMENT, + "WAIT": UNSUPPORTED, + "XDRAW": UNSUPPORTED, + "&": UNSUPPORTED, + "?": STATEMENT + }; + var reservedKeys = (function() { + // Need longer stems first: ATN/AT, ONERR/ON, NOTRACE/NOT + var keys = [], name; + for (name in reserved) { + if (Object.prototype.hasOwnProperty.call(reserved, name)) { + keys.push(name); + } + } + keys.sort(); + keys.reverse(); + return keys; + } ()); + + // states are 'normal' and 'comment' + + return { + startState: function() { + return { + state: 'normal' + }; + }, + + token: function(stream, state) { + var name, i; + + if (state.state === 'normal') { + if (stream.eatSpace()) { + return null; + } + else if (/[0-9.]/.test(stream.peek())) { + stream.eatWhile(/[0-9]/); + if (stream.peek() === '.') { + stream.next(); + stream.eatWhile(/[0-9]/); + } + if (/[eE]/.test(stream.peek())) { + stream.next(); + stream.eatWhile(/[ \u00a0]/); + if (stream.peek() === '-' || stream.peek() === '+') { + stream.next(); + } + stream.eatWhile(/[ \u00a0]/); + stream.eatWhile(/[0-9]/); + } + return 'basic-number'; + } + else if (stream.peek() === '"') { + stream.next(); + while (!stream.eol()) { + if (stream.next() === '"') { + break; + } + } + return 'basic-string'; + } + else if (/[;=<>+\-*\/\^(),]/.test(stream.peek())) { + stream.next(); + return 'basic-operator'; + } + else if (stream.peek() === ':') { + stream.next(); + return 'basic-separator'; + } + else if (stream.match('REM', true, true)) { + stream.eatWhile(/[ \u00a0]/); + if (!stream.eol()) { + state.state = 'comment'; + } + return 'basic-statement'; + } + + // TODO: Applesoft-style space ignoring within reserved words + + for (i = 0; i < reservedKeys.length; i += 1) { + name = reservedKeys[i]; + if (stream.match(name, true, true)) { + return reserved[name]; + } + } + + if (/[A-Za-z]/.test(stream.peek())) { + stream.next(); + stream.eatWhile(/[A-Za-z0-9]/); + if (stream.peek() === '$' || stream.peek() === '%') { + stream.next(); + } + return 'basic-identifier'; + } + + stream.next(); + return 'basic-error'; + } + else if (state.state === 'comment') { + while (!stream.eol()) { + stream.next(); + } + state.state = 'normal'; + return 'basic-comment'; + } + else { + throw 'WTF!?'; + } + + + } + }; +}); + +CodeMirror.defineMIME("text/x-basic", "basic"); +CodeMirror.defineMIME("text/x-applesoft", "basic"); diff --git a/dos.js b/dos.js new file mode 100644 index 0000000..65d39b3 --- /dev/null +++ b/dos.js @@ -0,0 +1,509 @@ +// +// Applesoft BASIC in Javascript +// DOS Emulation + +// Copyright (C) 2009-2011 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// Usage: +// var dos = new DOS( tty ) // hooks tty's writeChar/readChar/readLine +// dos.reset() // Close all open buffers + +/*global basic*/ + +function DOS(tty) { + /*jslint bitwise: false, browser: true*/ + + var DOSErrors = { + LANGUAGE_NOT_AVAILABLE: [1, "Language not available"], + RANGE_ERROR: [2, 'Range error'], + WRITE_PROTECTED: [4, 'Write protected'], + END_OF_DATA: [5, 'End of data'], + FILE_NOT_FOUND: [6, 'File not found'], + VOLUME_MISMATCH: [7, 'Volume mismatch'], + IO_ERROR: [8, 'I/O error'], + DISK_FULL: [9, 'Disk full'], + FILE_LOCKED: [10, 'File locked'], + INVALID_OPTION: [11, 'Invalid option'], + NO_BUFFERS_AVAILABLE: [12, 'No buffers available'], + FILE_TYPE_MISMATCH: [13, 'File type mismatch'], + PROGRAM_TOO_LARGE: [14, 'Program too large'], + NOT_DIRECT_COMMAND: [15, 'Not direct command'] + }, + + STORAGE_PREFIX = 'vfs/', + + // For MON/NOMON + MON_I = 1, + MON_C = 2, + MON_O = 4, + + // Original versions of hooked I/O routines + tty_readLine, + tty_readChar, + tty_writeChar, + + // character output state + commandBuffer = "", + commandMode = false, + + // I/O buffers + buffers = {}, + activebuffer = null, + mode = "", + + // other state + monico = 0; + + function doserror(msg) { + throw new basic.RuntimeError(msg[1], msg[0]); + } + + // Internal - crack arguments e.g. ",S6,D1" + function parseArgs(str, opts) { + opts = opts || ''; + + // Set these to zero so they're always defined when passed into command handlers + var args = { + V: 0, // Volume + D: 0, // Drive + S: 0, // Slot + L: 0, // Length + R: 0, // Record/Relative + B: 0, // Byte + A: 0, // Address + C: undefined, // Echo Commands + I: undefined, // Echo Input + O: undefined // Echo Output + }; + + while (str.match(/^,?\s*([VDSLRBACIO])\s*([0-9]+|\$[0-9A-Fa-f]+)?\s*([\x20-\x7E]*)/)) { + if (opts.indexOf(RegExp.$1) === -1) { + doserror(DOSErrors.INVALID_OPTION); + } + args[RegExp.$1] = Number(RegExp.$2); + str = RegExp.$3; + } + + if (str.length > 0) { + doserror(DOSErrors.INVALID_OPTION); + } + + return args; + } + + + + //---------------------------------------------------------------------- + // Browser-side VFS + //---------------------------------------------------------------------- + + function vfs_set(key, value) { + return window.localStorage.setItem(STORAGE_PREFIX + key, encodeURIComponent(value)); + } + function vfs_get(key) { + var item = window.localStorage.getItem(STORAGE_PREFIX + key); + return item !== null ? decodeURIComponent(item) : null; + } + function vfs_remove(key) { + return window.localStorage.removeItem(STORAGE_PREFIX + key); + } + + + //---------------------------------------------------------------------- + // Implementation + //---------------------------------------------------------------------- + + this.reset = function _reset() { + buffers = {}; + activebuffer = null; + mode = ""; + }; + + function unlink(filename) { + var item = vfs_get(filename); + + if (item === null) { + doserror(DOSErrors.FILE_NOT_FOUND); + } + + vfs_remove(filename); + } + + function rename(oldname, newname) { + var item = vfs_get(oldname); + + if (item === null) { + doserror(DOSErrors.FILE_NOT_FOUND); + } + + vfs_remove(oldname); + vfs_set(newname, item); + } + + function open(filename, recordlength) { + if (recordlength === 0) { + // Sequential access + recordlength = 1; + } + + // Peek in the VFS cache first + var file = vfs_get(filename), + req, url, async; + if (file === null) { + // Not cached - do a synchronous XmlHttpRequest for the file here + req = new XMLHttpRequest(); + try { + url = "vfs/" + encodeURIComponent(filename.replace(/\./g, '_')) + ".txt"; + async = false; + req.open("GET", url, async); + req.send(null); + if (req.status === 200 || req.status === 0) { // 0 for file:// protocol + file = req.responseText.replace(/\r\n/g, "\r"); + vfs_set(filename, file); + } + } catch (e) { + // File doesn't exist - APPEND/READ will fail + throw e; + } + } + + // Create a buffer for the file + buffers[filename] = { + file: file, + recordlength: recordlength, + recordnum: 0, + filepointer: 0 + }; + } + + function append(filename, recordlength) { + // Normal open logic + open(filename, recordlength); + + if (!buffers.hasOwnProperty(filename)) { + doserror(DOSErrors.FILE_NOT_FOUND); + } + + var buf = buffers[filename]; + + // Then seek to the end of the file + buf.filepointer = buf.file.length; + buf.recordnum = Math.floor(buf.filepointer / buf.recordlength); + } + + function close(filename) { + var buf, fn; + + // If not specified, close all buffers + if (!filename) { + for (fn in buffers) { + if (buffers.hasOwnProperty(fn)) { + close(fn); + } + } + return; + } + + buf = buffers[filename]; + if (buf) { + // flush changes to "disk" + vfs_set(filename, buf.file); + + delete buffers[filename]; + if (buf === activebuffer) { + activebuffer = null; + mode = ""; + } + } + } + + function read(filename, recordnum, bytenum) { + var buf = buffers[filename]; + if (!buf) { + // Open file if no such named buffer, but don't create it + open(filename, 0); + buf = buffers[filename]; + } + + if (buf.file === null) { + doserror(DOSErrors.FILE_NOT_FOUND); + } + + // Set the file position + buf.recordnum = recordnum; + buf.filepointer = buf.recordlength * recordnum + bytenum; + + // Set the active buffer into read mode + activebuffer = buf; + mode = "r"; + } + + function write(filename, recordnum, bytenum) { + var buf = buffers[filename]; + if (!buf) { + // Must open the file before writing + doserror(DOSErrors.FILE_NOT_FOUND); + } + + if (buf.file === null) { + // If we still don't have it, create in VFS if necessary + vfs_set(filename, ''); + buf.file = ''; + } + + // Set up the file position + buf.recordnum = recordnum; + if (buf.recordlength > 1) { + buf.filepointer = buf.recordlength * recordnum; + } + buf.filepointer += bytenum; + + // Set the active buffer into write mode + activebuffer = buf; + mode = "w"; + } + + function position(filename, records) { + var buf = buffers[filename]; + if (!buf) { + // Open file if no such named buffer, but don't create it + open(filename, 0, false); + buf = buffers[filename]; + } + + // Set up the file position + buf.recordnum += records; + buf.filepointer += buf.recordlength * records; + + } + + //---------------------------------------------------------------------- + // Command Dispatch + //---------------------------------------------------------------------- + function executeCommand(command) { + // Delegate to various commands + // http://www.xs4all.nl/~fjkraan/comp/apple2faq/app2doscmdfaq.html + // http://www.textfiles.com/apple/ANATOMY/ + + var filename, filename2, args, slot; + + if (monico & MON_C && tty) { + tty.writeString(command + "\r"); + } + + if (command.match(/^MON([\x20-\x7E]*)/)) { + // MON[,C][,I][,O] Traces DOS 3.3 commands ('Commands', 'Input' and 'Output') + args = parseArgs(RegExp.$1, 'ICO'); + + if (args.I !== undefined) { + monico |= MON_I; + } + if (args.C !== undefined) { + monico |= MON_C; + } + if (args.O !== undefined) { + monico |= MON_O; + } + + } else if (command.match(/^NOMON([\x20-\x7E]*)/)) { + // NOMON[,C][,I][,O] Cancels tracing of DOS 3.3 commands ('Commands', 'Input' and 'Output') + args = parseArgs(RegExp.$1, 'ICO'); + if (args.I !== undefined) { + monico &= ~MON_I; + } + if (args.C !== undefined) { + monico &= ~MON_C; + } + if (args.O !== undefined) { + monico &= ~MON_O; + } + } else if (command.match(/^OPEN\s*([\x20-\x2B\x2D-\x7E]+)(,[\x20-\x7E]*)?/)) { + // OPEN filename[,Llen] Opens a text file. + filename = RegExp.$1; + args = parseArgs(RegExp.$2, 'L'); + open(filename, args.L); + } else if (command.match(/^APPEND\s*([\x20-\x2B\x2D-\x7E]+)(,[\x20-\x7E]*)?/)) { + // APPEND filename Appends to a text file. + filename = RegExp.$1; + args = parseArgs(RegExp.$2); + append(filename, args.L); + } else if (command.match(/^CLOSE\s*([\x20-\x2B\x2D-\x7E]+)?(,[\x20-\x7E]*)?/)) { + // CLOSE [filename] Closes specified (or all) open text files. + filename = RegExp.$1; + close(filename); + } else if (command.match(/^POSITION\s*([\x20-\x2B\x2D-\x7E]+)(,[\x20-\x7E]*)?/)) { + // POSITION filename[,Rnum] Advances position in text file. + filename = RegExp.$1; + args = parseArgs(RegExp.$2, 'R'); + position(filename, args.R); + } else if (command.match(/^READ\s*([\x20-\x2B\x2D-\x7E]+)(,[\x20-\x7E]*)?/)) { + // READ filename[,Rnum][,Bbyte] Reads from a text file. + filename = RegExp.$1; + args = parseArgs(RegExp.$2, 'RB'); + read(filename, args.R, args.B); + } else if (command.match(/^WRITE\s*([\x20-\x2B\x2D-\x7E]+)(,[\x20-\x7E]*)?/)) { + // WRITE filename[,Rnum][,Bbyte] Writes to a text file. + filename = RegExp.$1; + args = parseArgs(RegExp.$2, 'RB'); + write(filename, args.R, args.B); + } else if (command.match(/^DELETE\s*([\x20-\x2B\x2D-\x7E]+)(,[\x20-\x7E]*)?/)) { + // DELETE filename Delete a file + filename = RegExp.$1; + args = parseArgs(RegExp.$2); + unlink(filename); + } else if (command.match(/^RENAME\s*([\x20-\x2B\x2D-\x7E]+),\s*([\x20-\x2B\x2D-\x7E]+)(,[\x20-\x7E]*)?/)) { + // RENAME filename,filename Rename a file + filename = RegExp.$1; + filename2 = RegExp.$2; + args = parseArgs(RegExp.$3); + rename(filename, filename2); + } else if (command.match(/^PR#\s*([\x20-\x2B\x2D-\x7E]+)(,[\x20-\x7E]*)?/)) { + // PR# slot Direct output to slot + slot = Number(RegExp.$1); + args = parseArgs(RegExp.$2); + if (slot === 0) { + if (tty.setFirmwareActive) { tty.setFirmwareActive(false); } + } else if (slot === 3) { + if (tty.setFirmwareActive) { tty.setFirmwareActive(true); } + } else { + doserror(DOSErrors.RANGE_ERROR); + } + } else if (command.match(/^$/)) { + // Null command - terminates a READ/WRITE, but doesn't CLOSE + // (leaves record length intact on open buffer) + activebuffer = null; + mode = ""; + } else { + doserror(DOSErrors.INVALID_OPTION); + } + } + + + //---------------------------------------------------------------------- + // Install TTY Hooks + //---------------------------------------------------------------------- + tty_readLine = tty.readLine; + tty_readChar = tty.readChar; + tty_writeChar = tty.writeChar; + + tty.readLine = function _dos_readLine(callback, prompt) { + + var string = "", c, data, len, fp, buffer; + if (mode === "r") { + // Cache for performance + data = activebuffer.file; + len = data.length; + fp = activebuffer.filepointer; + + if (fp >= len) { + doserror(DOSErrors.END_OF_DATA); + } + + buffer = []; + while (fp < len) { + // Sequential Access + c = data[fp]; + fp += 1; + if (c === "\r" || c === "\n" || c === "\x00") { + break; + } else { + buffer.push(c); + } + } + activebuffer.filepointer = fp; + string = buffer.join(""); + + if (monico & MON_I) { + tty.writeString(prompt + string + "\r"); + } + + // Non-blocking return + setTimeout(function() { callback(string); }, 0); + } else { + tty_readLine(callback, prompt); + } + + }; + + tty.readChar = function _dos_readChar(callback) { + + var character = ""; + if (mode === "r") { + if (activebuffer.filepointer >= activebuffer.file.length) { + doserror(DOSErrors.END_OF_DATA); + } + + character = activebuffer.file[activebuffer.filepointer]; + activebuffer.filepointer += 1; + + if (monico & MON_I && tty) { + tty_writeChar(character); + } + + // Non-blocking return + setTimeout(function() { callback(character); }, 0); + } else { + tty_readChar(callback); + } + }; + + tty.writeChar = function _dos_writeChar(c) { + + if (commandMode) { + if (c === "\r") { + commandMode = false; + executeCommand(commandBuffer); + commandBuffer = ""; + } else { + commandBuffer += c; + } + return; + } else if (c === "\x04") { + commandBuffer = ""; + commandMode = true; + return; + } + + if (mode === "w") { + var buf, d; + + if (monico & MON_O) { + tty_writeChar(c); + } + + buf = activebuffer; + // Extend file to necessary length + while (buf.filepointer > buf.file.length) { + buf.file += "\x00"; + } + + // Append or insert character + if (buf.filepointer === buf.file.length) { + buf.file += c; + } else { + d = buf.file.substring(0, buf.filepointer); + d += c; + d += buf.file.substring(buf.filepointer + 1); + buf.file = d; + } + + buf.filepointer += 1; + } else { + tty_writeChar(c); + } + + }; // writeChar +} diff --git a/feed.js b/feed.js new file mode 100644 index 0000000..1373b60 --- /dev/null +++ b/feed.js @@ -0,0 +1,66 @@ +// +// Atom to HTML - fetch a feed, inject it as dl/dt/dd +// + +// Copyright (C) 2009-2010 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +function atomToHtml(uri, element) { + + var READYSTATE_UNINITIALIZED = 0; + var READYSTATE_LOADING = 1; + var READYSTATE_LOADED = 2; + var READYSTATE_INTERACTIVE = 3; + var READYSTATE_COMPLETE = 4; + + var xhr = new XMLHttpRequest(); + var async = true; + xhr.open("GET", uri, async); + xhr.onreadystatechange = function() { + if (xhr.readyState === READYSTATE_COMPLETE) { + if ((xhr.status === 200 || xhr.status === 0) && xhr.responseXML) { + var doc = xhr.responseXML; + var entries = doc.getElementsByTagName('entry'); + var html = []; + + html.push('
'); + + for (var i = 0; i < entries.length; i += 1) { + var entry = entries[i]; + try { + var entryHTML = []; + entryHTML.push('
', entry.getElementsByTagName('title')[0].childNodes[0].nodeValue); + entryHTML.push('
', entry.getElementsByTagName('content')[0].childNodes[0].nodeValue); + html.push(entryHTML.join('')); + } catch (e) { + if (console && console.log) { console.log("Error:", e); } + } + } + + html.push('
'); + + element.innerHTML = html.join(''); + } else { + element.innerHTML = 'Unable to load feed'; + } + } + }; + + try { + xhr.send(null); + } catch (e) { + element.innerHTML = 'Unable to load feed'; + } +} + diff --git a/feed.xml b/feed.xml new file mode 100644 index 0000000..ae1b7d8 --- /dev/null +++ b/feed.xml @@ -0,0 +1,789 @@ + + + + http://www.calormen.com/Applesoft/ + Applesoft BASIC in Javascript - Change Log + 2011-12-06T23:00:00Z + + + Joshua Bell + inexorabletash@hotmail.com + http://www.calormen.com/ + + + + + + 2011-12-06 + http://www.calormen.com/Applesoft/20111206 + 2011-12-06T23:00:00Z + + <p> + Added <code>PEEK</code> and <code>POKE</code> shim for 230 (Hi-Res plotting page), to + enable drawing on the back buffer for animations. + + + + 2011-04-20 + http://www.calormen.com/Applesoft/20110420 + 2011-04-20T21:00:00Z + + <p> + Re-added support for running under + <a href="http://en.wikipedia.org/wiki/Windows_Script_Host">Windows Scripting Host</a> and added + <a href="http://www.mozilla.org/rhino/">Mozilla Rhino</a> support too. + + + + 2011-04-16 + http://www.calormen.com/Applesoft/20110416 + 2011-04-16T23:00:00Z + + <p> + Total internal revamp: Now a compiler rather than interpreter. Source errors are reported + by BASIC line number as well as source line/column. + <p> + Display defaults to 40 columns, emulates 80-column firmware more accurately. Character output + (<code>CHR$()</code>, <code>INVERSE</code>, etc) tweaked to match Apple + behavior. + <p> + Files written via DOS now persist in your browser via <a href="http://dev.w3.org/html5/webstorage/">Web Storage</a>. + <p> + Floating point and integer overflows are caught rather than propagating infinities and NaNs. + <p> + <code>DATA</code> statements and <code>INPUT</code> entries parse + more accurately as comma delimited, optionally-quoted strings. <code>RE-ENTER?</code> + is shown on invalid <code>INPUT</code> (and can be trapped via <code>ONERR</code>) + <p> + Added <code>HGR2</code> and page-flipping <code>POKE</code> shims, plus a few <code>CALL</code> shims + for graphics. Hires graphics are now to a 280x192 bitmap, rather than trying to be sneaky with a 140x192 bitmap. + <p> + Error codes can be distinguished in <code>ONERR</code> via <code>PEEK(222)</code>. + Out-of-memory and stack-overflow conditions reported where possible (this is + <a href="http://cautionsingularityahead.blogspot.com/2011/03/stack-overflow-and-out-of-memory-in.html"> + non-standard across browsers</a>). + <p> + Tweaked samples that were dependent on language/environment quirks. + <p> + Updated code editor to (the much improved) <a href="http://codemirror.net/">CodeMirror 2.0</a>. On parse errors, + the cursor is moved to the offending line/character. + + + + 2011-01-29 + http://www.calormen.com/Applesoft/20110129 + 2011-01-29T23:30:00Z + + <p> + Fixed error handling issues, e.g. DOS errors w/ <code>ONERR</code> and syntax + errors e.g. <code>10 INPUT PRINT</code> + </p> + <p> + Added <code>HSCRN(x,y)</code> extension function. + </p> + <p> + Fix mouse-as-joystick to hit full range of 0...255. + </p> + + + + 2011-01-26 + http://www.calormen.com/Applesoft/20110126 + 2011-01-26T23:00:00Z + + <p> + No longer show paddles/joysticks automatically; rely on mouse-as-joystick primarily. + </p> + <p> + Use <a href="http://flashcanvas.net/">FlashCanvas</a> for older IE versions, instead of + <a href="http://excanvas.sourceforge.net/">excanvas</a>, and switch to plotting hires + pixels/lines directly rather than relying on canvas scaling and line drawing. + </p> + <p> + Added Gaussian Distribution 2D plot sample, by John Russ + </p> + + + + 2011-01-25 + http://www.calormen.com/Applesoft/20110125 + 2011-01-25T21:00:00Z + + <p> + Added compatibility shims for <code>PEEK(78)</code> and <code>PEEK(79)</code> + for seeding the random number generator. On a real Apple these are incremented during the input + polling loop and are a good source of entropy for seeding a random number generator. In this + interpreter, they are simply generated by the JavaScript <code>Math.random()</code> function. + </p> + + + + 2010-11-21 + http://www.calormen.com/Applesoft/20101121 + 2010-11-21T19:00:00Z + + <p> + Added lexical highlighting in code editor via <a href="http://codemirror.net">CodeMirror</a>. Note that this only highlights tokens, it does not check statement or expression syntax. It will highlight invalid tokens and unsupported statements. + <p> + Mousing over the screen now updates paddle position - try the lo-res painting demo for an example. + </p> + + <p> + Lots of internal code cleanup with hopefully no behavior changes. + </p> + + + + 2010-11-18 + http://www.calormen.com/Applesoft/20101118 + 2010-11-18T19:00:00Z + + <p> + Fix <code>RETURN</code> and <code>POP</code> + from inside a <code>FOR ... NEXT</code> loop. + </p> + <p> + Fix <code>TRACE</code> and <code>NOTRACE</code> + </p> + + + + 2010-11-13 + http://www.calormen.com/Applesoft/20101113 + 2010-11-13T19:00:00Z + + <p> + Added <code>SPEED=</code> shim (does nothing) + </p> + <p> + Fixed <code>SPC()</code> and <code>TAB()</code> + </p> + <p> + Work around + <a href="http://code.google.com/p/chromium/issues/detail?id=58144">Chrome bug</a> + to show full error alert text. + </p> + + + + 2010-08-29 + http://www.calormen.com/Applesoft/20100829 + 2010-08-29T11:22:00Z + + <p> + Added "Echo to Printer" option to allow copy/paste of output + </p> + <p> + Big refactor of internals. Statement parsing and execution now separated. A library of statement functions are + used for execution. Hopefully nothing broke - all unit tests still pass. + </p> + + + + 2010-05-04 + http://www.calormen.com/Applesoft/20100504 + 2010-05-04T20:28:00-08:00 + + <p> + When run under <code>cscript.exe</code>, the program still blocks until the user + presses Enter when a <code>GET</code> statement executes, but the entered + characters are returned by subsequent <code>GET</code> statements. + </p> + + <p> + Added Hello World Sine Wave sample by Jamie Beu. + </p> + + + + 2009-11-01 + http://www.calormen.com/Applesoft/20091101 + 2009-11-01T14:22:00-08:00 + + <p> + Changes are now recorded in an <a href="feed.xml">Atom Feed</a>. + </p> + + + + 2009-10-24 + http://www.calormen.com/Applesoft/20091024 + 2009-10-24T12:00:00-08:00 + + <p> + Now licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a> + </p> + + + + 2009-10-15 + http://www.calormen.com/Applesoft/20091015 + 2009-10-15T12:00:00-08:00 + + <p> + Fixed bug with <code>POKE</code> and negative addresses (introduced 2009-05-15, bleah) + </p> + + + + 2009-06-10 + http://www.calormen.com/Applesoft/20090610 + 2009-06-10T12:00:00-08:00 + + <p> + Added <a href="http://en.wikipedia.org/wiki/Boy%27s_surface">Boy's Surface</a> sample by Lukas Innig + </p> + + + + 2009-05-08 + http://www.calormen.com/Applesoft/20090508b + 2009-05-08T13:00:00-08:00 + + <p> + Fixed running with <code>cscript</code> + </p> + <p>Slight performance tweaks for IE c/o explicit sizing</p> + + + + 2009-05-08 + http://www.calormen.com/Applesoft/20090508 + 2009-05-08T12:00:00-08:00 + + <p> + Tracked down source of IE perf issues when drawing with paddles; when the thumb/stick moves, + IE does a relayout/repaint of any content above the paddle in the HTML flow. If I delete the + page header it's silky-smooth. Unfortunately, any text above the screen seems to make it fall + off the deep end - so no fix yet without gutting the page. + </p> + <p> + Undid "Line breaks from <code>PRINT</code> now clear to the right edge" - doesn't repro on Apple. <em>What was I thinking?</em> + </p> + + + + 2009-05-06 + http://www.calormen.com/Applesoft/20090506 + 2009-05-06T12:00:00-08:00 + + <p> + A bunch of performance tweaks based on IE8's JavaScript profiler. While they look good on paper, + they mean diddly-squat to perceived performance. Don't precalc default variable values, avoid DOM + changes that are no-ops, and (sigh) don't scan the whole screen looking for <code>FLASH</code>-styled + cells - maintain a list instead so perf isn't impacted if there are none. + </p> + + + + 2009-05-01 + http://www.calormen.com/Applesoft/20090501 + 2009-05-01T12:00:00-08:00 + + <p> + Expressions are now just-in-time compiled to JavaScript. Screen updates are the real bottleneck, though, + so this isn't a big performance boost. Performance comparison (on my 1.73GHz machine) of the lores Mandelbrot set demo: + <ul> + <li>Google Chrome (V8 JavaScript compiler): 25% faster (21s vs. 27s)</li> + <li>Firefox 3: 14% faster (64s vs. 73s)</li> + <li>Internet Explorer 8: &lt;1% faster (249s vs. 251s)</li> + </ul> + So not a huge win except on faster execution engines. But this is just the first step... + </p> + <p> + Fixed <code>POKE 216,x</code> shim to disable <code>ONERR</code> handler + </p> + + + + 2009-04-30 + http://www.calormen.com/Applesoft/20090430 + 2009-04-30T12:00:00-08:00 + + <p> + Rejiggered internal value storage/passing system to use fundamental JavaScript types instead of <code>{number: value}</code> or + <code>{string: value}</code>. I didn't trust JavaScript's type system when I first wrote this code. + </p> + + + + 2009-04-26 + http://www.calormen.com/Applesoft/20090426 + 2009-04-26T12:00:00-08:00 + + <p> + Performance - made <code>GOTO</code>/<code>GOSUB</code> not do a linear scan to find the line (d'oh). Significant perf boost for IE. + </p> + <p>Added Unit Tests sample. Coverage is not complete but it's getting there.</p> + <p> + <code>RND()</code> with negative now consistently reseeds (added custom pseudoranom number generator) + </p> + <p> + <code>FOR I = 10 TO 1 : PRINT I : NEXT</code> now correctly prints <samp>10</samp> then finishes (was previously incorrectly inferring <code>STEP -1</code>) + </p> + + + + 2009-04-25 + http://www.calormen.com/Applesoft/20090425 + 2009-04-25T12:00:00-08:00 + + <p> + Line breaks from <code>PRINT</code> now clear to the right edge of the text window + </p> + <p> + Automatically show input devices if <code>PDL()</code> called + </p> + <p>Added Zhodani Relay Station Placement example (run after generating a sector with Traveller Sector Generator)</p> + + + + 2009-04-24 + http://www.calormen.com/Applesoft/20090424 + 2009-04-24T12:00:00-08:00 + + <p> + Fixed a bug where changing text mode (e.g. <code>PR#3</code>) after calling <code>HGR</code> would break split-screen mode. + </p> + + + + 2009-04-14 + http://www.calormen.com/Applesoft/20090414 + 2009-04-14T12:00:00-08:00 + + <p> + Updated to an <a href="http://explorercanvas.blogspot.com/2009/03/new-explorer-canvas-release.html">IE8-compatible</a> version of <a href="http://code.google.com/p/explorercanvas/">excanvas</a>. + Updated <a href="excanvas.patch">my excanvas patch to support scaling</a>. + </p> + + + + 2009-04-05 + http://www.calormen.com/Applesoft/20090405 + 2009-04-05T12:00:00-08:00 + + <p> + Allow <code>DEF FN</code> to be invalid (errors occur in <code>FN</code>, per Applesoft) + </p> + <p> + Fixed <code>PR#0</code> in Safari + </p> + <p> + Added <code> + RENAME <var>old</var>,<var>new</var> + </code>to DOS + </p> + <p> + Fixed <code>LIST</code> for assignment statements with no <code>LET</code> + </p> + <p> + Fixed operator spacing for <code>LIST</code> + </p> + <p> + Fixed parsing of empty <code>REM</code> statements + </p> + <p>Program would execute after a tokenization error was encountered - fixed.</p> + <p>Added Traveller Sector Generator sample</p> + + + + 2009-03-07 + http://www.calormen.com/Applesoft/20090307 + 2009-03-07T12:00:00-08:00 + + <p>Fixed cursor blinking</p> + <p>Added Connections, Puzzler, and Squiggle by Gregg Buntin</p> + + + + 2009-03-06 + http://www.calormen.com/Applesoft/20090306 + 2009-03-06T12:00:00-08:00 + + <p> + Addressed IE performance issues: sped up Text and LoRes screen initialization, don't use classes for characters (<em>sigh</em>). + </p> + <p> + Fixed <code>PRINT SPC()</code> + </p> + + + + 2009-03-05 + http://www.calormen.com/Applesoft/20090305 + 2009-03-05T12:00:00-08:00 + + <p> + <code>PRINT CHR$(7)</code> now rings a <code>BELL</code> (if your browser has an audio/wav WAV handler configured) + </p> + <p>Reimplemented the text display (TTY) using bitmap font, to mimic the look of 40/80 column text (no more copy/paste, alas)</p> + <p> + Added MouseText support. <code>INVERSE:PRINT CHR$(27);"XY";CHR$(24):NORMAL</code> + </p> + <p> + The ASCII Pac-Man sample was really <em>Unicode</em> Pac-Man, which the bitmap font doesn't support, so it broke. So I cheated. + </p> + + + + 2009-03-01 + http://www.calormen.com/Applesoft/20090301 + 2009-03-01T12:00:00-08:00 + + <p>Added Scribble sample, by William Simms</p> + + + + 2009-02-12 + http://www.calormen.com/Applesoft/20090212 + 2009-02-12T12:00:00-08:00 + + <p>Added February Surprise sample by Antti Pirskanen</p> + + + + 2008-11-08 + http://www.calormen.com/Applesoft/20081108 + 2008-11-08T12:00:00-08:00 + + <p>Ignore whitespace-only lines, as a convenience</p> + <p>Added ASCII PAC-MAN(ish) sample by Michael Kemp</p> + + + + 2008-10-19 + http://www.calormen.com/Applesoft/20081019 + 2008-10-19T12:00:00-08:00 + + <p>Added TEXT ADVENTURE sample by Floyd McWilliams.</p> + <p>Allow string literals to be terminated by end-of-line (suggested by Mike Kienenberger for compatibility)</p> + + + + 2008-09-18 + http://www.calormen.com/Applesoft/20080918 + 2008-09-18T12:00:00-08:00 + + <p>Fixed a case where syntax errors were ignored</p> + + + + 2008-09-17 + http://www.calormen.com/Applesoft/20080917 + 2008-09-17T12:00:00-08:00 + + <p>Fixed input focus to work in Google Chrome</p> + <p> + Fixed <code>READ</code> to support multiple variables, e.g. <code>READ I,J,S$</code> + </p> + + + + 2008-08-23 + http://www.calormen.com/Applesoft/20080823 + 2008-08-23T12:00:00-08:00 + + <p>Added Save/Load buttons that let you save your work to a cookie</p> + <p>Added DRAWING PROGRAM sample by Brian Broker</p> + <p>Fixed power operator (^) which wasn't being parsed correctly</p> + <p>Fixed subtle bug with string comparisons (result was double-typed as number and string)</p> + + + + 2008-05-01 + http://www.calormen.com/Applesoft/20080501 + 2008-05-01T12:00:00-08:00 + + <p> + Fixed <code>NEXT I,J,...</code> to terminate multiple loops - thanks to Scott Alfter for pointing this out + </p> + <p> + Bowing to popular demand, it now supports <code>?</code> as an alias for <code>PRINT</code> + </p> + + + + 2008-03-15 + http://www.calormen.com/Applesoft/20080315 + 2008-03-15T12:00:00-08:00 + + <p> + Implemented <code>ONERR GOTO line</code> and <code>RESUME</code>, including <code>POKE 216,0</code> + </p> + <p>Added demo for ONERR, added ONERR support to sequential file access demo</p> + <p>Fix hires graphics on Safari - not sure when it broke</p> + + + + 2008-03-14 + http://www.calormen.com/Applesoft/20080314 + 2008-03-14T12:00:00-08:00 + + <p> + Code cleanup c/o <a href="http://www.jslint.com">jslint.com</a> + </p> + <p> + Bug fix: <code>INPUT A,B,C</code> no longer worked. Probably mis-re-factored at some point. + </p> + + + + 2007-12-08 + http://www.calormen.com/Applesoft/20071208 + 2007-12-08T12:00:00-08:00 + + <p> + Implement file writing (to client-side VFS only), including <code>APPEND</code> operations + </p> + <p> + Added DOS <code>DELETE</code> command + </p> + <p> + <code>GR</code> does implicit <code>HTAB 1 : VTAB 24</code> + </p> + <p> + <code>PEEK(49168)</code> has the same effect as <code>POKE 49168,N</code> + </p> + <p> + As a convenience, <code>PEEK</code> and <code>POKE</code> at 49200/-16336 (speaker toggle) now accepted, but a no-op + </p> + <p> + As a convenience, spaces now accepted before <code>=</code> for<code>COLOR=</code> and <code>HCOLOR=</code> + </p> + + + + 2007-11-22 + http://www.calormen.com/Applesoft/20071122 + 2007-11-22T12:00:00-08:00 + + <p>Added button to submit your sample (via email) for inclusion</p> + <p>Added SIMPLE.PONG sample c/o USENET post by mad.scientist.jr</p> + <p>Improved comment handling (doesn't tokenize)</p> + + + + 2007-10-22 + http://www.calormen.com/Applesoft/20071022 + 2007-10-22T12:00:00-08:00 + + <p> + Make <code>GET</code> support keyboard flag, so <code>IF PEEK(-16384) > 127 THEN GET A$</code> works + </p> + + + + 2007-10-20 + http://www.calormen.com/Applesoft/20071020 + 2007-10-20T12:00:00-08:00 + + <p>Bug fix: User could type after hitting Stop. Now TTY state is reset.</p> + <p> + Added missing statement: <code>ON expr GOSUB ...</code> + </p> + <p> + <code>RND(0)</code> returns last, negative reseeds + </p> + + + + 2007-10-14 + http://www.calormen.com/Applesoft/20071014 + 2007-10-14T12:00:00-08:00 + + <p>Fixed location of paddle button 3 (C060)</p> + + + + 2007-09-22 + http://www.calormen.com/Applesoft/20070922 + 2007-09-22T12:00:00-08:00 + + <p> + Implemented scaling in <a target="_blank" href="http://excanvas.sourceforge.net/"> + ExplorerCanvas</a> (<a target="_blank" href="excanvas.js">source</a>); hires now scaled somewhat correctly in IE + </p> + <p>Bug fixes: HOME would force full-screen text; HPLOT can now plot a single pixel</p> + + + + 2007-09-20 + http://www.calormen.com/Applesoft/20070920 + 2007-09-20T12:00:00-08:00 + + <p> + Added hires support via <a target="_blank" href="http://www.whatwg.org/specs/web-apps/current-work/#canvas">canvas</a> tag + </p> + <p>Display switches (POKE 49232...49239, not counting page 2) supported.</p> + <p>Added text window support: POKE 32,left : POKE 33,width : POKE 34,top : POKE 35,bottom</p> + + + + 2007-09-16 + http://www.calormen.com/Applesoft/20070916 + 2007-09-16T12:00:00-08:00 + + <p> + Added full screen lores support via <a target="_blank" href="reference.htm#Poke">POKE</a> 29234,0 + </p> + <p>Fixed keyboard input on Safari - hacky, but logical</p> + + + + 2007-09-15 + http://www.calormen.com/Applesoft/20070915 + 2007-09-15T12:00:00-08:00 + + <p>Added Mandelbrot set demo to DEMOS</p> + <p> + Added <a target="_blank" href="reference.htm#Peek">PEEK</a> and <a target="_blank" href="reference.htm#Poke">POKE</a> shims + </p> + <p>Added paddle buttons: Home = 0 = Open Apple, End = 1 = Solid Apple, Page Up = 2, Page Down = 3</p> + <p>Added Caps Lock (defaults to on; real Caps Lock key toggles it; this means it usually ends up in an inverted state)</p> + <p>Round numerical results to 8 decimal places (hacky)</p> + + + + 2007-09-10 + http://www.calormen.com/Applesoft/20070910 + 2007-09-10T12:00:00-08:00 + + <p>Added demo file links, cleaned up UI a bit.</p> + <p>Added hacky PR#0/PR#3 support (to set 40 columns)</p> + + + + 2007-09-09 + http://www.calormen.com/Applesoft/20070909 + 2007-09-09T12:00:00-08:00 + + <p>Execute multiple steps before yielding. Increases perceived performance by about 10x.</p> + <p>Adjust lores colors per Linards Ticmanis on comp.sys.apple2.</p> + <p>Added Joystick, reorganized web pages</p> + + + + 2007-09-04 + http://www.calormen.com/Applesoft/20070904 + 2007-09-04T12:00:00-08:00 + + <p>Added MON/NOMON support.</p> + <p>Fixed bugs with: READ into arrays, two argument MID$, e-format number parsing, DOS null command</p> + + + + 2007-09-03 + http://www.calormen.com/Applesoft/20070903 + 2007-09-03T12:00:00-08:00 + + <p>Bugfixes: SPC() and TAB() followed by ; in PRINT statements. DOS parameter lists can include spaces.</p> + + + + 2007-09-02 + http://www.calormen.com/Applesoft/20070902 + 2007-09-02T12:00:00-08:00 + + <p>Oops - FRE is a function not a statement. Fixed!</p> + + + + 2007-09-01 + http://www.calormen.com/Applesoft/20070901 + 2007-09-01T12:00:00-08:00 + + <p>Implemented DATA/READ/RESTORE</p> + + + + 2007-08-31 + http://www.calormen.com/Applesoft/20070831 + 2007-08-31T12:00:00-08:00 + + <p>Implemented DEF FN</p> + + + + 2007-08-30 + http://www.calormen.com/Applesoft/20070830 + 2007-08-30T12:00:00-08:00 + + <p>Implemented DIM. File reads complete.</p> + + + + 2007-08-27 + http://www.calormen.com/Applesoft/20070827 + 2007-08-27T12:00:00-08:00 + + <p> + Added preliminary <a target="_blank" href="reference.htm#DOSQuickReference">DOS implementation</a>. Sequential access read only; there's a file called "JABBERWOCKY" to try. + </p> + + + + 2007-08-24 + http://www.calormen.com/Applesoft/20070824 + 2007-08-24T12:00:00-08:00 + + <p>Fixed bugs with string variables, key presses in IE, and HTML tweaks for better layout and lo-res sizing</p> + + + + 2007-06-05 + http://www.calormen.com/Applesoft/20070605 + 2007-06-05T12:00:00-08:00 + + <p>Added paddle support (PDL)</p> + + + + 2007-06-03 + http://www.calormen.com/Applesoft/20070603 + 2007-06-03T12:00:00-08:00 + + <p>Added lores graphics support (GR, PLOT, HLIN, VLIN, COLOR=, SCRN)</p> + + + + 2007-05-01 + http://www.calormen.com/Applesoft/20070501 + 2007-05-01T12:00:00-08:00 + + <p>Extracted step mechanism from interpreter, so web page can introduce delays; no longer case-sensitive to keywords</p> + + + + 2007-04-29 + http://www.calormen.com/Applesoft/20070429 + 2007-04-29T12:00:00-08:00 + + <p>Fixed command-line mode again</p> + + + + 2007-04-27 + http://www.calormen.com/Applesoft/20070427 + 2007-04-27T12:00:00-08:00 + + <p>Added screen emulation (e.g. HOME, HTAB, VTAB) and input (e.g. GET)</p> + + + + 2007-04-24 + http://www.calormen.com/Applesoft/20070424 + 2007-04-24T12:00:00-08:00 + + <p>Integrated into browser (display and event model)</p> + + + + 2007-04-21 + http://www.calormen.com/Applesoft/20070421 + 2007-04-21T12:00:00-08:00 + + <p>Project started; interpreter functional via WSH on Windows</p> + + + diff --git a/font-40col.png b/font-40col.png new file mode 100644 index 0000000000000000000000000000000000000000..156cbe279021c54b886ed387eaad9e020f229770 GIT binary patch literal 19128 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 TGw=&}X6)G+_DR)_gJ1t2Iip)Q literal 0 HcmV?d00001 diff --git a/font-80col.png b/font-80col.png new file mode 100644 index 0000000000000000000000000000000000000000..5c99807862c8bc4205c143205f92ec40fbe120bd GIT binary patch literal 4387 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 AUjP6A literal 0 HcmV?d00001 diff --git a/font.png b/font.png new file mode 100644 index 0000000000000000000000000000000000000000..33abd9c54dcd4e0a5e730e42f6af525f43cd655b GIT binary patch literal 3872 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 literal 0 HcmV?d00001 diff --git a/hires.js b/hires.js new file mode 100644 index 0000000..9b00b75 --- /dev/null +++ b/hires.js @@ -0,0 +1,152 @@ +// +// Applesoft BASIC in Javascript +// High Resolution Graphics (HiRes) Emulation +// + +// Copyright (C) 2009-2011 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// This variation does not rely on a canvas element with the same dimensions +// as the pixel buffer; instead, it paints pixels on the canvas using rectangles. +// This works even if the underlying canvas implementation does not support +// scaling (e.g. fallbacks for IE using VML or Flash) + +// Usage: +// +// var hires = new LoRes( element, width, height ) +// hires.clear() +// hires.setColor( color_index ) +// hires.plot( x, y ) +// hires.plot_to( x, x ) +// hires.getPixel( x, x ) // for "HSCRN" +// hires.show( bool ) +// { width: w, height: h } = hires.getScreenSize() +// +// Example: +// +// +// + +function HiRes(element, width, height) { + var COLORS, // Apple II to HTML color table + last_x = 0, + last_y = 0, + pixels = [], + color = 0, + context = element.getContext("2d"); + + pixels.length = width * height; + + // Colors c/o USENET: + // Date: Wed, 05 Sep 2007 01:04:20 +0200 + // From: Linards Ticmanis + // Newsgroups: comp.sys.apple2 + // Subject: Re: Double hires mode color artifacts + // Message-ID: <46dde477$0$4527$9b4e6d93@newsspool3.arcor-online.net> + + COLORS = [ + '#000000', // Black 1 + '#2fbc1a', // Green + '#d043e5', // Violet + '#ffffff', // White 1 + '#000000', // Black 2 + '#d06a1a', // Orange + '#2f95e5', // Medium Blue + '#ffffff' // White 2 + ]; + + this.clear = function(use_color) { + var i; + if (!use_color) { + context.clearRect(0, 0, element.width, element.height); + pixels = []; + pixels.length = width * height; + } else { + context.fillStyle = COLORS[color]; + context.fillRect(0, 0, element.width, element.height); + pixels = []; + pixels.length = width * height; + for (i = 0; i < pixels.length; i += 1) { + pixels[i] = color; + } + } + }; + + + this.setColor = function(newColor) { + color = Math.floor(newColor) % COLORS.length; + }; + + + function drawPixel(x, y) { + var sx = element.width / width, + sy = element.height / height; + context.fillRect(x * sx, y * sy, sx, sy); + pixels[x + y * width] = color; + } + + this.plot = function(x, y) { + context.fillStyle = COLORS[color]; + drawPixel(x, y); + + last_x = x; + last_y = y; + + }; + + this.plot_to = function(x, y) { + var x0 = last_x, y0 = last_y, x1 = x, y1 = y, + dx = Math.abs(x1 - x0), + dy = Math.abs(y1 - y0), + sx = (x0 < x1) ? 1 : -1, + sy = (y0 < y1) ? 1 : -1, + err = dx - dy, + e2; + + while (true) { + this.plot(x0, y0); + + if (x0 === x1 && y0 === y1) { return; } + e2 = 2 * err; + if (e2 > -dy) { + err -= dy; + x0 += sx; + } + if (e2 < dx) { + err += dx; + y0 += sy; + } + } + last_x = x; + last_y = y; + + }; + + this.getPixel = function(x, y) { + /*jslint bitwise:false*/ + return pixels[y * width + x] >>> 0; + }; + + this.getScreenSize = function() { + return { width: width, height: height }; + }; + + this.show = function(state) { + element.style.visibility = state ? "visible" : "hidden"; + }; +} diff --git a/index.htm b/index.htm new file mode 100644 index 0000000..634df88 --- /dev/null +++ b/index.htm @@ -0,0 +1,452 @@ + + + + +Applesoft BASIC in JavaScript + + + + + + + + + +

Applesoft BASIC in Javascript

+

+By Joshua Bell +| Applesoft BASIC Quick Reference +| Notes & Known Issues +| To Do +| Links +| History + +

Related projects: + Logo in Javascript + | Streaming video to an Apple II - vnIIc +

+ +
+ + +
+
+
+ + +
+
+
+ + + + + +
+ Enter code below +       + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ +

Notes & Known Issues

+
    +
  • The BASIC program is compiled to JavaScript before execution. Syntax errors are therefore detected at compile-time + rather than at run-time as on a traditional interpreter. For example, the following program would run without errors + on an Apple since the erroneous second statement is never reached. 10 END : CHR$(PRINT) +
  • Handling of BASIC code that does not match the canonical LIST output format may not behave as on an Apple: +
      +
    • Keyword parsing differs from Applesoft command line. For example FOR I = S TO P doesn't collapse into FOR I = STOP. +
    • The interpreter doesn't actually care about line numbers for statement ordering (just for GOTO/GOSUB targets and IF statements). So 20 PRINT "A", 10 PRINT "B" will just print A, then B +
    +
  • To improve readability, lines may start with : and continue the previously numbered line. +
  • Floating point overflow is only detected on variable assignment. +
  • The DOS operating system implements only a subset of DOS 3.3 and ProDOS useful for basic file I/O. +
  • Except for a small number of compatibility shims for common operations (e.g. keyboard strobe), commands that refer to assembly routines (PEEK, POKE, CALL, USR etc.), shape tables, or tape I/O are not implemented. +
  • Commands that operate on the program itself (LIST, RUN, DEL, etc.) are not implemented. +
  • You can run your basic programs from the command line (with only basic text input and output, and no graphics or DOS commands): +
      +
    • On Windows, download basic.js and run from a command prompt via: + cscript.exe basic.js your_basic_program.txt +
    • On Mac/Linux, install Mozilla Rhino, + download basic.js and run from the command prompt via: + java -jar PATH_TO/js.jar basic.js your_program.txt +
    +
+ +

To Do

+
    +
  • Implement DOS functionality for consoles +
+ + + + +

History

+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/lores.js b/lores.js new file mode 100644 index 0000000..ef96704 --- /dev/null +++ b/lores.js @@ -0,0 +1,192 @@ +// +// Applesoft BASIC in Javascript +// Low Resolution Graphics (LoRes) Emulation +// + +// Copyright (C) 2009-2011 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// Usage: +// +// var lores = new LoRes( element, width, height ) +// lores.clear() +// lores.setColor( color_index ) +// lores.plot( x, y ) +// lores.hlin( x1, x2, y ) +// lores.vlin( x1, x2, y ) +// lores.show( bool ) +// color_index = lores.getPixel( x, y ) +// { width: w, height: h } = lores.getScreenSize() +// +// Example: +// +// +// +//
+ +function LoRes(element, width, height) { + + /*jslint browser: true*/ + + var COLORS, // Apple II to HTML color table + loresPixel = [], // element references + pixels = [], // color values + color = 0; // current color + + // Colors c/o USENET: + // Date: Wed, 05 Sep 2007 01:04:20 +0200 + // From: Linards Ticmanis + // Newsgroups: comp.sys.apple2 + // Subject: Re: Double hires mode color artifacts + // Message-ID: <46dde477$0$4527$9b4e6d93@newsspool3.arcor-online.net> + + COLORS = [ + '#000000', // Black + '#901740', // Deep Red + '#402ca5', // Dark Blue + '#d043e5', // Purple + '#006940', // Dark Green + '#808080', // Gray 1 + '#2f95e5', // Medium Blue + '#bfabff', // Light Blue + '#402400', // Brown // WAS #405400, error pointed out by MJM + '#d06a1a', // Orange + '#808080', // Gray 2 + '#ff96bf', // Pink + '#2fbc1a', // Light Green + '#bfd35a', // Yellow + '#6fe8bf', // Aquamarine + '#ffffff' // White + ]; + + function init() { + var x, y, table, tbody, tr, td; + + pixels = []; + pixels.length = width * height; + loresPixel = []; + loresPixel.length = width * height; + + table = document.createElement('table'); + table.className = 'loresDisplay'; + + tbody = document.createElement('tbody'); + for (y = 0; y < height; y += 1) { + tr = document.createElement('tr'); + tr.className = 'loresRow'; + for (x = 0; x < width; x += 1) { + td = document.createElement('td'); + td.className = 'loresPixel'; + td.style.backgroundColor = 'black'; + + loresPixel[y * width + x] = td; + pixels[y * width + x] = 0; + + tr.appendChild(td); + } + tbody.appendChild(tr); + } + table.appendChild(tbody); + + element.innerHTML = ""; + element.appendChild(table); + } + + this.clear = function() { + var x, y, pixel; + for (y = 0; y < height; y += 1) { + for (x = 0; x < width; x += 1) { + pixel = loresPixel[y * width + x]; + pixel.style.backgroundColor = "black"; + pixels[y * width + x] = 0; + } + } + + }; + + this.setColor = function(newColor) { + color = Math.floor(newColor) % COLORS.length; + }; + + function plot(x, y) { + var pixel = loresPixel[y * width + x]; + if (pixel) { + pixel.style.backgroundColor = COLORS[color]; + pixels[y * width + x] = color; + } + } + + this.plot = function(x, y) { + plot(x, y); + }; + + this.getPixel = function(x, y) { + if (0 <= x && x < width && + 0 <= y && y < height) { + + return pixels[y * width + x]; + } else { + return 0; + } + }; + + this.hlin = function(x1, x2, y) { + var x; + if (x1 > x2) { + x = x1; + x1 = x2; + x2 = x; + } + + for (x = x1; x <= x2; x += 1) { + plot(x, y); + } + }; + + this.vlin = function(y1, y2, x) { + var y; + if (y1 > y2) { + y = y1; + y1 = y2; + y2 = y; + } + + for (y = y1; y <= y2; y += 1) { + plot(x, y); + } + }; + + this.getScreenSize = function() { + return { width: width, height: height }; + }; + + this.show = function(state) { + element.style.visibility = state ? "visible" : "hidden"; + + }; + + //---------------------------------------------------------------------- + // Constructor Logic + //---------------------------------------------------------------------- + + init(); +} + + diff --git a/paddles.js b/paddles.js new file mode 100644 index 0000000..3cd7b5a --- /dev/null +++ b/paddles.js @@ -0,0 +1,140 @@ +// +// Applesoft BASIC in Javascript +// Paddle and Joystick Emulation +// + +// Copyright (C) 2009-2011 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// Usage: +// +// initPaddle( device_element, thumb_element, callback_function ); +// initJoystick( device_element, thumb_element, callback_function_x, callback_function_y ); +// +// Example: +// +// +// +//
Slide the Paddle!
+//
Twiddle me!
+ +/*extern document,window,addEvent,removeEvent */ + +function initDevice(device, thumb, fn_x, fn_y) { + device.style.position = "relative"; + device.style.overflow = "hidden"; + + thumb.style.position = "absolute"; + thumb.style.left = 0; + thumb.style.top = 0; + + thumb.last_x = 0; + thumb.last_y = 0; + + var onStickDrag = function (e) { + e.returnValue = false; + e.cancelBubble = true; + if (e.stopPropagation) { e.stopPropagation(); } + if (e.preventDefault) { e.preventDefault(); } + + if (fn_x) { + var x = e.clientX - thumb.originX + thumb.posX; + var min_x = 0; + var max_x = device.clientWidth - thumb.offsetWidth; + if (x < min_x) { x = min_x; } + if (x > max_x) { x = max_x; } + + if (x != thumb.last_x) { + thumb.last_x = x; + thumb.style.left = x + "px"; + fn_x((x - min_x) / (max_x - min_x)); + } + } + + if (fn_y) { + var y = e.clientY - thumb.originY + thumb.posY; + var min_y = 0; + var max_y = device.clientHeight - thumb.offsetHeight; + if (y < min_y) { y = min_y; } + if (y > max_y) { y = max_y; } + + if (y != thumb.last_y) { + thumb.last_y = y; + thumb.style.top = y + "px"; + fn_y((y - min_y) / (max_y - min_y)); + } + } + + return false; + }; + + var onStickUp = function (e) { + e.returnValue = false; + e.cancelBubble = true; + if (e.stopPropagation) { e.stopPropagation(); } + if (e.preventDefault) { e.preventDefault(); } + + removeEvent(document, "mousemove", onStickDrag); + removeEvent(document, "mouseup", onStickUp); + if (thumb.releaseCapture) { thumb.releaseCapture(true); } + + return false; + }; + + var onStickDown = function (e) { + e.returnValue = false; + e.cancelBubble = true; + if (e.stopPropagation) { e.stopPropagation(); } + if (e.preventDefault) { e.preventDefault(); } + + addEvent(document, "mousemove", onStickDrag); + addEvent(document, "mouseup", onStickUp); + if (thumb.setCapture) { thumb.setCapture(true); } + + if (fn_x) { + thumb.originX = e.clientX; + thumb.posX = parseInt(thumb.style.left, 10); + } + + if (fn_y) { + thumb.originY = e.clientY; + thumb.posY = parseInt(thumb.style.top, 10); + } + + return false; + }; + + device.appendChild(thumb); + + addEvent(thumb, "mousedown", onStickDown); +} + +function initPaddle(device, control, fn) { + initDevice(device, control, fn); +} + +function initJoystick(device, control, fn_x, fn_y) { + initDevice(device, control, fn_x, fn_y); +} diff --git a/printer.js b/printer.js new file mode 100644 index 0000000..f5c5ef1 --- /dev/null +++ b/printer.js @@ -0,0 +1,95 @@ +// +// Applesoft BASIC in Javascript +// Printer (for copying output) +// + +// Copyright (C) 2009-2011 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +function Printer(tty) { + + // For closures + var self = this; + + // Create new window and document + var w = window.open('about:blank', '_blank', 'width=500,height=400,status=0,location=0,menubar=0,toolbar=0'); + var body = w.document.getElementsByTagName('body')[0]; + body.style.fontFamily = 'Courier, Monospace'; + body.style.backgroundColor = '#ffffff'; + body.style.backgroundImage = "url('http://calormen.com/Star_Trek/ASCII/lpt.jpg')"; + body.style.color = '#000000'; + body.style.paddingLeft = '50px'; + + var paper = w.document.createElement('div'); + paper.style.whiteSpace = 'pre'; + body.appendChild(paper); + + var tty_writeChar = tty.writeChar; + tty.writeChar = function(c) { + + tty_writeChar(c); + + switch (c.charCodeAt(0)) { + case 0: + case 1: + case 2: + case 3: + case 4: // DOS hook + case 5: + case 6: + case 7: // (BEL) bell + case 8: // (BS) backspace + case 9: + case 11: // (VT) clear EOS + case 12: // (FF) clear + case 14: // (SO) normal + case 15: // (SI) inverse + case 16: + case 17: // (DC1) 40-column + case 18: // (DC2) 80-column + case 19: // (DC3) stop list + case 20: + case 21: // (NAK) quit (disable 80-col card) + case 22: // (SYN) scroll + case 23: // (ETB) scroll up + case 24: // (CAN) disable mousetext + case 25: // (EM) home + case 26: // (SUB) clear line + case 27: // (ESC) enable mousetext + case 28: // (FS) forward space + case 29: // (GS) clear EOL + case 30: // (RS) gotoXY + case 31: + break; + + case 10: // (LF) line feed + case 13: // (CR) return + paper.appendChild(w.document.createTextNode('\n')); + break; + + default: + paper.appendChild(w.document.createTextNode(c)); + break; + } + + paper.parentElement.scrollTop = paper.parentElement.scrollHeight; + }; + + w.onunload = function() { + if (self.onclose) { + self.onclose(); + } + tty.writeChar = tty_writeChar; + }; +} diff --git a/reference.htm b/reference.htm new file mode 100644 index 0000000..0479d66 --- /dev/null +++ b/reference.htm @@ -0,0 +1,570 @@ + + + +Applesoft BASIC Reference + + + + +
+ +

Applesoft BASIC Quick Reference

+ +

+This is intended as a quick reference for the Applesoft BASIC in JavaScript by Joshua Bell. +

+ +

+Extensions beyond Applesoft BASIC are called out with footnotes. +

+ +

See also:

+ + + + + +

Statements

+ + +

Variable Control

+
+
CLEAR
Clear all variables +
[LET] var = expr
Assign variable +
DIM var( size [ , size2 ...] ) [ , var2( size [ , size2 ...] ) ... ]
Allocate array +
DEF FN f(var ) = expr
Define function of a single variable [1] +
+

Flow Control

+
+
GOTO
Go to line number +
GOSUB line
Go to subroutine +
RETURN
Return from subroutine +
ON expr GOTO line [, line2 ... ]
Branch based on index (value = 1, 2, ...) +
ON expr GOSUB line [, line2 ... ]
Subroutine branch based on index (value = 1, 2, ...) +
POP
Convert last gosub into a goto +
FOR var = start TO end [ STEP incr ]
Loop with counter variable +
NEXT [var [, var ...] ]
End of loop(s) +
IF expr THEN statement
IF expr GOTO line
Conditional; if expr is false, rest of line is skipped +
END
Terminate program +
STOP
Break, as if an error occurred +
+

Error Handling

+
+
ONERR GOTO line
Set error hook +
RESUME
Retry line that caused ONERR GOTO +
+

Input/Output

+
+
PRINT expr [ [;,] expr2 ... ] [;]
Output text +
INPUT [string ;] var [, var2 ... ]
Read line of input +
GET var
Read single key +
HOME
Clear text display +
HTAB expr
Position text cursor horizontally +
VTAB expr
Position text cursor vertically +
INVERSE
Set output mode to black-on-white +
FLASH
Set output mode to flashing +
NORMAL
Set output mode to white-on-black +
TEXT
Set display to text mode +
+

Miscellaneous

+
+
REM [ comment ]
Begin a comment; rest of line is skipped +
TRACE
Turn on trace mode (line numbers printed) +
NOTRACE
Turn off trace mode +
+

Inline Data

+
+
DATA value [, value2 ... ]
Define inline data +
READ var [, var2 ... ]
Read the next DATA value +
RESTORE
Restore the DATA pointer to the first value +
+

Lo-Res Graphics

+
+
GR
Set display to lores mode, clear screen +
COLOR= expr
Set lores color (0...15) +
PLOT expr, expr
Plot lores point (x = 0...39, y = 0...40/48) +
HLIN expr, expr AT expr
Plot horizontal line (x1, x2 at y) +
VLIN expr, expr AT expr
Plot vertical line (y1, y2 at x) +
+

Hi-Res Graphics

+
+
HGR
Set display to hires mode, clear screen +
HGR2
Set display to hires mode (page 2), clear screen +
HPLOT [TO] expr, expr [ TO expr, expr ] ...
Plot hires point/line (x=0...279, y=0...191) +
HCOLOR= expr
Set hires color (0...7) +
+

Hi-Res Shape Tables - NOT IMPLEMENTED

+
+
ROT= expr
Set hires shape table rotation (0...63) +
SCALE= expr
Set hires shape table scale (1...255) +
DRAW expr [ AT expr, expr ]
Draw hires shape table shape in color +
XDRAW expr [ AT expr, expr ]
Draw hires shape table shape with XOR +
+

Interpreter and Program State - NOT IMPLEMENTED

+
+
CONT
Continue from a STOP +
DEL
Delete lines of program +
LIST [ expr [, expr ] ]
List lines of program +
NEW
Clear program and variables +
RUN [ expr ]
Start program execution at line +
+

Native Platform Interaction - NOT IMPLEMENTED

+
+
HIMEM: expr
Set upper address of variable memory +
IN# expr
Direct input from slot +
LOMEM: expr
Set lower address of variable memory +
WAIT expr, expr [, expr]
Wait until memory location masked by second argument equals third argument (or zero) +
+

Cassette Tape - NOT IMPLEMENTED

+
+
LOAD
Load program from cassette +
RECALL
Load variables from cassette +
SAVE
Save program to cassette +
STORE
Save variables to cassette +
SHLOAD
Load hires shape table from cassette +
+

Compatibility Shims

+
+
SPEED= expr
Set character output delay - has no effect +
POKE expr, expr
Set memory location to value +
    +
  • POKE 32,n - Text window left edge +
  • POKE 33,n - Text window width +
  • POKE 34,n - Text window top edge +
  • POKE 35,n - Text window bottom +
  • POKE 36,n - Text cursor x +
  • POKE 37,n - Text cursor y +
  • POKE 216,n - ONERR flag (n < 128 disables ONERR handler) +
  • POKE 230,n - Hi-Res plotting page (32 = page 1, 64 = page 2) +
  • POKE 49168,0 - clear keyboard strobe +
  • POKE 49200,0 - toggle speaker (no-op) +
  • POKE 49232,0 - graphics mode +
  • POKE 49233,0 - text mode +
  • POKE 49234,0 - full graphics +
  • POKE 49235,0 - split screen +
  • POKE 49238,0 - lores +
  • POKE 49239,0 - hires +
+ +
CALL expr
Call native routine +
    +
  • CALL -3100 - reveal hi-res page 1 +
  • CALL -3086 - clear current hi-res page to black +
  • CALL -3082 - clear current hi-res page to current color +
  • CALL 54951 - clear stack (cancel pending FOR-NEXT loops and GOSUBs) +
+ +
PR# expr
Direct output to slot +
    +
  • PR#0 - set 40 column mode +
  • PR#3 - set 80 column mode +
+ +
+ + +

Functions

+ + +

Numeric Functions

+
+
ABS( expr )
Absolute value of number +
ATN( expr )
Arctangent of number +
COS( expr )
Cosine of number +
EXP( expr )
Raise e to number +
INT( expr )
Integer part of number +
LOG( expr )
Natural log of number +
RND( expr )
Pseudo-random number generator (0 repeats last, negative reseeds) +
SGN( expr )
Sign of number (-1,0,1) +
SIN( expr )
Sine of number +
SQR( expr )
Square root of number +
TAN( expr )
Tangent of number +
+

String Functions

+
+
LEN( expr )
Length of string +
LEFT$( expr, expr )
Left portion of (string, length) +
MID$( expr, expr [, expr] )
Substring of (string, start character, length) +
RIGHT$( expr, expr )
Right portion of (string, length) +
+

Type Conversion Functions

+
+
ASC( expr )
ASCII code for first character of string +
CHR$( expr )
Character at specified ASCII code point[3] +
STR$( expr )
String representation of number +
VAL( expr )
Parse string into number +
+

System Interaction Functions

+
+
FRE( expr )
Garbage collect strings (returns 0) +
PDL( expr )
Paddle position (paddle number) +
POS( expr )
Horizontal cursor position +
SCRN( expr, expr )
Lores color at pixel (x,y) +
HSCRN( expr, expr )
Hires color at pixel (x,y)[4] +
USR( expr )
Execute assembly code at address, return accumulator value - NOT IMPLEMENTED +
+

User Defined Functions

+
+
FN f( expr )
Execute user defined function [1] +
+ +

Function Compatibility Shims

+
+
PEEK( expr )
Value at memory location +
    +
  • PEEK(32) - Text window left edge +
  • PEEK(33) - Text window width +
  • PEEK(34) - Text window top edge +
  • PEEK(35) - Text window bottom +
  • PEEK(36) - Text cursor x +
  • PEEK(37) - Text cursor y +
  • PEEK(78) & PEEK(79) - Random-Number Field +
  • PEEK(222) - Last error code +
  • PEEK(230) - Hi-Res plotting page (32 = page 1, 64 = page 2) +
  • PEEK(49152) - Read Keyboard +
  • PEEK(49168) - Clear Keyboard strobe +
  • PEEK(49200) - Click Speaker (no-op) +
  • PEEK(49248) - Read Paddle Button #3 - Use the PageDown key +
  • PEEK(49249) - Read Paddle Button #0 - Use the Home key +
  • PEEK(49250) - Read Paddle Button #1 - Use the End key +
  • PEEK(49251) - Read Paddle Button #2 - Use the PageUp or Shift key +
+ +
+ + +

Operators

+ + +

Comparison Operators

+
+
=
Equality[2] +
<
Less than +
>
Greater than +
<=
=<
Less than or equal +
>=
=>
Greater than or equal +
<>
><
Not equal +
+

Boolean Operators

+
+
AND
Conjunction +
OR
Disjunction +
NOT
Negation +
+

Arithmetic Operators

+
+
^
Exponentiation +
*
Multiplication +
/
Division +
+
Addition +
-
Subtraction +
+

String Operators

+
+
+
String Concatenation +
+ + +

Error Codes

+ +

Error codes can be determined by calling +PEEK(222) in an ONERR handler.

+ +
+
0
Next without for +
16
Syntax error - Not generated +
22
Return without gosub +
42
Out of data +
53
Illegal quantity +
69
Overflow +
77
Out of memory - Not generated by all browsers +
90
Undefined statement +
107
Bad subscript +
120
Redimensioned array +
133
Division by zero +
163
Type mismatch +
176
String too long - Not generated +
191
Formula too complex - Not generated by all browsers +
224
Undefined function +
254
Re-enter +
255
Break +
+ + + + +

DOS 3.3 / ProDOS Quick Reference

+ + +

See also

+ + +

DOS Commands

+
+
MON[,C][,I][,O]
Traces DOS 3.3 commands ('Commands', 'Input' and 'Output') +
NOMON[,C][,I][,O]
Cancels tracing of DOS 3.3 commands ('Commands', 'Input' and 'Output') +
OPEN filename[,Llen]
Opens a text file. +
APPEND filename
Appends to a text file. +
CLOSE [filename]
Closes specified (or all) open text files. +
POSITION filename[,Rnum]
Advances position in text file. +
READ filename[,Rnum][,Bbyte]
Reads from a text file. +
WRITE filename[,Rnum][,Bbyte]
Writes to a text file +
DELETE filename
Delete a file +
RENAME oldname,newname
Rename a file +
PR# slot
Same as the BASIC command +
+

Other DOS commands are NOT IMPLEMENTED.

+

Some sample files are present in a server-side store loaded on-demand into a client-side virtual file system (VFS). Creating or writing to a file will write to the VFS. Subsequent reads will read from the VFS. Files may be deleted from the VFS. These changes will not persist if the browser is refreshed or closed.

+ +

DOS Error Codes

+ +

Error codes can be determined by calling +PEEK(222) in an ONERR handler.

+ +
+
1
Language not available - Not generated +
2
Range error - Not generated +
4
Write protected - Not generated +
5
End of data +
6
File not found +
7
Volume mismatch - Not generated +
8
I/O error - Not generated +
9
Disk full - Not generated +
10
File locked - Not generated +
11
Invalid option +
12
No buffers available - Not generated +
13
File type mismatch - Not generated +
14
Program too large - Not generated +
15
Not direct command - Not generated +
+ + +

Input and Output

+ + +

Input

+ +

+The page attempts to emulate an Apple II keyboard. Note that the keyboard +API available in Web browsers is not standardized and is poorly defined; +a best-effort has been made testing on available systems and browsers. +

+ +

+The Open Apple and Closed Apple keys on later Apple II models +correspond to the Button #0 and Button #1 inputs and are emulated on modern keyboards +with the Home and End keys respectively. (Unfortunately, browsers +are currently unable to distinguish the left and right Alt or Command keys.) +

+ +

+Since the Tab key is necessary for keyboard access to browser functions and +the rest of the web page, it is not available. Otherwise, special keys can be detected +using GET (blocking) or PEEK(49152) (non-blocking): +

+ + +
CHR$(8)Left arrow +
CHR$(10)Down arrow +
CHR$(11)Up arrow +
CHR$(13)Enter or Return +
CHR$(21)Right arrow +
CHR$(24)Clear +
CHR$(27)Escape +
CHR$(127)Delete or Backspace +
+ + +

Output

+ +

+The page attempts to emulate the display of an Apple II system with +80-column card firmware, which can be activated with the +PR#3 statement. +

+ +

+When printing characters, CHR$ functions as expected for values +from 32-126 (printable ASCII). Control characters have the typical Apple II meanings: +

+ + +
CHR$(4)DOS command escape prefix +
CHR$(7)Make a "beep" (if your browser supports it) +
CHR$(8)Backspace (move cursor left, wrap up) +
CHR$(10)Line feed (move cursor down) +
CHR$(13)Carriage return (move cursor down and to left edge) +
CHR$(127)Displays a cursor glyph +
+ +

+If 80-column firmware is active, the following additional codes are available: +

+ +
CHR$(11)Clears from the cursor position to the end of the window +
CHR$(12)Move cursor to upper left and clear window +
CHR$(14)Set normal text output +
CHR$(15)Set inverse text output +
CHR$(17)Set display to 40 columns +
CHR$(18)Set display to 80 columns +
CHR$(21)Deactivate the 80-column firmware +
CHR$(22)Scroll display down, preserving cursor position +
CHR$(23)Scroll display up, preserving cursor position +
CHR$(24)Disable mousetext +
CHR$(25)Move cursor to upper left (but don't clear window) +
CHR$(26)Clear the current line +
CHR$(27)Enable mousetext +
CHR$(28)Forward space (move cursor right, wrap down) +
CHR$(29)Clear from cursor position to end of line +
+ +

+The text window can be changed and cursor finely controlled +with POKE 32,n ... POKE 37,n +

+ + +

Process and Grammars

+ +

For the even geekier in the audience...

+ +

Compilation is done by splitting the input into tokens which are then +consumed by a recursive descent parser which outputs a JavaScript +object representing the program.

+ +

The token types (treated as terminals) are + reserved, + identifier, + string-literal, + number-literal, + operator, + line-number, + separator, + remark, + data-declaration + - take a peek at the code if you want the gruesome details. Source lines may + only start with line numbers or (as an extension) separators. Special statement + parsing is done while lexing: REM consumes anything to the next + line break, and DATA statements yeild an array of strings + from the comma-delimited, optionally-quoted values in the source. +

+ +
    +
  • [x] zero or one occurences of x +
  • {x} zero or more occurences of x +
  • x | y one of either x or y +
  • (x) grouping construct +
+ +

Overall program parsing is done with a recursive descent parser.

+ +
+    Program                  = Line { Line }
+    Line                     = line-number Statement { separator Statement }
+    Statement                = data-declaration | remark | Command | EmptyStatement
+    Command                  = identifier /*...*/ | reserved /*...*/
+
+ +

Statements ("commands" in the above grammar) are parsed with distinct cases for each statement type. +Most statements compile into a function call to a library of Applesoft routines. Expressions are parsed +with a standard recursive descent parser. The parser generates JavaScript expressions for each expression, +which are used as arguments for the library calls.

+ +
+    Expression               = OrExpression
+    OrExpression             = AndExpression [ 'OR' AndExpression ... ]
+    AndExpression            = RelationalExpression [ 'AND' RelationalExpression ... ]
+    RelationalExpression     = AdditiveExpression [ ( '=' | '<' | '>' | '<=' | '=<' | '>=' | '=>' | '<>' | '><' ) AdditiveExpression ... ]
+    AdditiveExpression       = MultiplicativeExpression [ ( '+' | '-' ) MultiplicativeExpression ... ]
+    MultiplicativeExpression = PowerExpression [ ( '*' | '/' ) PowerExpression ... ]
+    PowerExpression          = UnaryExpression [ '^' UnaryExpression ]
+    UnaryExpression          = ( '+' | '-' | 'NOT' ) UnaryExpression
+                              | FinalExpression
+    FinalExpression          = number-literal
+                              | string-literal
+                              | 'FN' user_function_name '(' Expression ')'
+                              | reserved '(' Expression [, Expression ...] ')'
+                              | identifier [ '(' Expression [, Expression ...] ')' ]
+                              | '(' Expression ')'
+
+ + +

Since Applesoft supports re-entrant error handling and synchronous input, +the output of the compiler is an array of statement-functions plus a driver +function which implements the logic for walking over the array.

+ + +

Extensions beyond Standard Applesoft

+ +
    +
  • + [1] DEF FN supports string and integer functions + e.g. DEF FN IN$(X$) = " " + X$ + (but return type must still match argument type) +
  • + [2] == is supported for equality comparisons, in addition to = +
  • + [3] When printing characters, CHR$ values greater than 255 generate glyphs that might be useful for certain maze games. +
  • + [4] HSCRN(x, y) is added to allow reading the + hires screen. On a real Apple this required a machine-language routine (or a shape table and XDRAW). + +
+ + + + diff --git a/samples/TRADER C.txt b/samples/TRADER C.txt new file mode 100644 index 0000000..8b41df7 --- /dev/null +++ b/samples/TRADER C.txt @@ -0,0 +1,302 @@ + 10 GOTO 10000 + 100 REM EDITION OF 2 NOV 1985 + 1000 A$ = LEFT$ (A$ + " ",1): IF A$ = "?" OR A$ = "CHANGE" THEN INPUT "WHAT SHIP LETTER? > ";A$:A$ = LEFT$ ("A" + A$,1):TY = ASC (A$) - 64: GOSUB 1500 + 1030 RETURN + 1500 PRINT CHR$ (4);"OPEN SHIPS, L100": PRINT CHR$ (4);"READ SHIPS, R";TY: INPUT SH$: PRINT CHR$ (4);"CLOSE": HOME : GOSUB 3000: PRINT FI$;" ";TI$;" ";NA$;: HTAB 30: PRINT " ";DA$: PRINT "5";BL$: VTAB 4: PRINT MID$ (SH$,69,15);" "; MID$ (SH$,52,15) + 1600 TN = VAL ( MID$ (SH$,3,4)): PRINT "TONNAGE: ";TN;:A$ = "STREAMLINED":SL$ = MID$ (SH$,28,1): IF SL$ = "U" THEN A$ = "UN" + A$ + 1610 PRINT " ";A$: PRINT "PERFORMANCE: ";: PRINT "JUMP-"; MID$ (SH$,8,1);:JP = VAL ( MID$ (SH$,8,1)):PN = VAL ( MID$ (SH$,10,1)):NA$ = MID$ (SH$,52,15):G = VAL ( MID$ (SH$,9,1)): PRINT " ";G;"-G":FU = VAL ( MID$ (SH$,23,4)): PRINT "FUEL TANKAGE: ";FU:FY = FU:CH = VAL ( MID$ (SH$,18,4)): PRINT "CARGO HOLD: ";CH + 1690 SR = VAL ( MID$ (SH$,12,2)): PRINT "STATEROOMS: ";SR:LP = VAL ( MID$ (SH$,15,2)): PRINT "LOW BERTHS: ";LP:CW = VAL ( MID$ (SH$,49,2)): PRINT "CREW: ";CW:SA = VAL ( MID$ (SH$,34,6)): PRINT "CREW SALARIES: ";SA:CS = VAL ( MID$ (SH$,41,7)): PRINT "SHIP COST: ";CS;" MCR" + 1740 AL$ = MID$ (SH$,86,2): PRINT "ALLEGIANCE: ";AL$: PRINT "SERVICE: ";:SE = VAL ( MID$ (SH$,32,1)): PRINT SE$(SE): PRINT "OPERATIONS: ";:OP = VAL ( MID$ (SH$,30,1)):TI$ = SE$(OP): PRINT TI$: PRINT "PAYMENTS: ";:PA$ = MID$ (SH$,89,3):PA = VAL (PA$): IF LEFT$ (PA$,1) = "S" THEN PRINT "HALF OF REVENUES." + 1820 IF VAL (PA$) > 0 THEN PRINT INT ((CS / 240) * 1E + 6);" FOR ";PA$;" MONTHS." + 1830 IF LEFT$ (PA$,1) < > "S" AND VAL (PA$) < 1 THEN PRINT "PAID OFF." + 1840 PRINT "CR FUND: ";CR:OV = (FU * 500) + ((CST / 480) * 1000000) + (LP * 100) + (SR * 2000) + (SAL / 2) + (CST * .001) + 100:OV = INT (OV): PRINT "MAX OVERHEAD: ";OV: VTAB 22: PRINT " ACCEPT SHIP. A-Z DISPLAYS OTHERS " : HTAB 1 : VTAB 23 : PRINT " / RETURNS TO SHIP LIST" + 1882 INPUT "ACCEPT SHIP? > ";A$: IF LEFT$ (A$,1) = "" THEN 1920 + 1900 TY = ASC ( LEFT$ (A$,1)) - 64: IF TY < 1 OR TY > 26 THEN A$ = "/":CR = 0:OH = 0: GOTO 1920 + 1910 GOTO 1500 + 1920 RETURN + 2000 PRINT CHR$ (4);"OPEN ";FI$;",L50": PRINT CHR$ (4);"READ ";FI$;",R";A: INPUT A$: IF OP < > 6 THEN 2110 + 2050 IF XL = 0 THEN 2110 + 2060 IF MID$ (A$,42,1) < > "*" THEN CR = CR + 50000 + 2070 A$ = LEFT$ (A$,41) + "*" + " ": PRINT CHR$ (4);"WRITE ";FI$;",R";A: PRINT A$:XR = XR - 1 + 2110 PRINT CHR$ (4);"CLOSE": RETURN + 3000 IF DA = 0 THEN 3060 + 3020 DD = DD + 1:DA = DA - 1: IF DD / 28 = INT (DD / 28) AND PA < > 0 THEN CR = CR - ((CST * 1E + 6) / 480):PA = PA - 1 + 3040 IF DD / 28 = INT (DD / 28) THEN CR = CR - SAL + 3050 IF DA > 0 THEN 3020 + 3060 IF DD > 365 THEN YR = YR + 1:DD = DD - 365:MNT = 1 + 3070 DA$ = RIGHT$ ("00" + STR$ (DD),3) + "-" + STR$ (YR): RETURN + 4000 P2 = VAL ( MID$ (A1$,10,1)): IF P2 = 0 AND ( MID$ (A1$,10,1)) < > "0" THEN P2 = ASC ( MID$ (A1$,10,1)) - 55 + 4020 T2 = VAL ( MID$ (A1$,14,1)): IF T2 = 0 AND ( MID$ (A1$,14,1)) < > "0" THEN T2 = ASC ( MID$ (A1$,14,1)) - 55 + 4030 P1 = VAL ( MID$ (A$(0),10,1)): IF P1 = 0 AND ( MID$ (A$(0),10,1)) < > "0" THEN P1 = ASC ( MID$ (A$(0),10,1)) - 55 + 4040 T1 = VAL ( MID$ (A$(0),14,1)): IF T1 = 0 AND ( MID$ (A$(0),14,1)) < > "0" THEN T1 = ASC ( MID$ (A$(0),14,1)) - 55 + 4050 TZ = 0: IF MID$ (A1$,36,1) = "A" THEN TZ = 1 + 4060 IF MID$ (A1$,36,1) = "R" THEN TZ = 2 + 4070 RETURN + 5000 D = FN B(8) + BR: IF D > 15 THEN D = 15 + 5050 IF D < 2 THEN D = 2 + 5060 AV = AV(D):CD = AV * CC * (1 - (BR * .05)):CC = CD * B: RETURN + 6000 FL = 0:J = JP: FOR FL = 1 TO 169:FL(FL) = 0:J(FL) = 0: NEXT :FL = 0: FOR M = 7 - J TO 7 + J:X = XC - 7 + M: FOR N = 7 - J TO 7 + J:Y = YC - 7 + N: IF X < 1 OR X > 32 THEN 6200 + 6120 IF Y < 1 OR Y > 40 THEN 6200 + 6130 IF PO(X,Y) = 0 THEN 6200 + 6140 IF X = XC AND Y = YC THEN 6200 + 6150 IF OP > 7 AND PO(X,Y) > 0 THEN 6200 + 6160 IF XC / 2 = INT (XC / 2) THEN 6190 + 6170 IF OD(N,M) = < J THEN FL = FL + 1:J(FL) = OD(N,M):FL(FL) = PO(X,Y): GOTO 6200 + 6180 GOTO 6200 + 6190 IF OD(14 - N,M) = < J THEN FL = FL + 1:J(FL) = OD(14 - N,M):FL(FL) = PO(X,Y): GOTO 6200 + 6200 VTAB 11: HTAB 2: PRINT " "; RIGHT$ ("0" + STR$ (X),2); RIGHT$ ("0" + STR$ (Y),2):FL(FL) = ABS (FL(FL)): NEXT : NEXT : RETURN + 7000 CC = 4000: FOR X = 18 TO 33 STEP 3: IF MID$ (A1$,X,2) = " " THEN 7090 + 7040 FOR X1 = 1 TO 23 STEP 2: IF X1 > 10 THEN 7070 + 7060 IF MID$ (A1$,X,2) = MID$ ("AGASHIINPO",X1,2) THEN CC = CC - 1000: GOTO 7080 + 7065 IF X1 < 11 THEN 7080 + 7070 IF MID$ (A1$,X,2) = MID$ ("BADEFLLONIVARI",X1 - 10,2) THEN CC = CC + 1000: GOTO 7080 + 7080 NEXT + 7090 NEXT : TL = VAL ( MID$ (A1$,14,1)): IF TL = 0 AND MID$ (A1$,14,1) = "0" THEN TL = 0: GOTO 7110 + 7103 IF TL > 0 AND TL < 10 THEN 7110 + 7105 TL = ASC ( MID$ (A1$,14,1)) - 55: IF TL > 19 THEN TL = TL - 1: IF TL > 24 THEN TL = TL - 1 + 7110 CC = CC + (TL * 100):ST$ = MID$ (A1$,6,1): IF ST$ = "A" THEN CC = CC - 1000 + 7140 IF ST$ = "C" THEN CC = CC + 1000 + 7150 IF ST$ = "D" THEN CC = CC + 2000 + 7160 IF ST$ = "E" THEN CC = CC + 3000 + 7170 IF ST$ = "X" THEN CC = CC + 5000 + 7180 CA$ = ST$ + "-" + MID$ (HE$,TL + 1,1) + " " + MID$ (A1$,18,15) + " CR" + STR$ (CC):A$ = CA$: RETURN + 8000 CC = 5000: FOR X = 5 TO 20 STEP 3: IF MID$ (B$,X,2) = " " THEN 8620 + 8040 FOR Y = 5 TO 20 STEP 3: IF MID$ (A$,Y,2) = "BA" THEN CC = CC - 2000: GOTO 8600 + 8060 IF MID$ (A$,Y,2) = " " THEN 8600 + 8070 IF MID$ (B$,X,2) < > "AG" THEN 8110 + 8080 FOR Z = 1 TO 15 STEP 2: IF MID$ (A$,Y,2) = MID$ ("AGASDEHIINLONARI",Z,2) THEN CC = CC + 1000 + 8100 NEXT + 8110 IF MID$ (B$,X,2) < > "AS" THEN 8150 + 8120 FOR Z = 1 TO 9 STEP 2: IF MID$ (A$,Y,2) = MID$ ("ASINNARIVA",Z,2) THEN CC = CC + 1000 + 8140 NEXT + 8150 IF MID$ (B$,X,2) < > "BA" THEN 8190 + 8160 FOR Z = 1 TO 3 STEP 2: IF MID$ (A$,Y,2) = MID$ ("AGIN",Z,2) THEN CC = CC + 1000 + 8180 NEXT + 8190 IF MID$ (B$,X,2) < > "DE" THEN 8230 + 8200 FOR Z = 1 TO 3 STEP 2: IF MID$ (A$,Y,2) = MID$ ("DENA",Z,2) THEN CC = CC + 1000 + 8220 NEXT + 8230 IF MID$ (B$,X,2) < > "FL" THEN 8270 + 8240 FOR Z = 1 TO 3 STEP 2: IF MID$ (A$,Y,2) = MID$ ("FLIN",Z,2) THEN CC = CC + 1000 + 8260 NEXT + 8270 IF MID$ (B$,X,2) < > "HI" THEN 8310 + 8280 FOR Z = 1 TO 3 STEP 2: IF MID$ (A$,Y,2) = MID$ ("HILORI",Z,2) THEN CC = CC + 1000 + 8300 NEXT + 8310 IF MID$ (B$,X,2) = "IC" AND MID$ (A$,Y,2) = "IN" THEN CC = CC + 1000 + 8320 IF MID$ (B$,X,2) < > "IN" THEN 8360 + 8330 FOR Z = 1 TO 21 STEP 2: IF MID$ (A$,Y,2) = MID$ ("AGASFLHILONIPORI",Z,2) THEN CC = CC + 1000 + 8350 NEXT + 8360 IF MID$ (B$,X,2) < > "LO" THEN 8400 + 8370 FOR Z = 1 TO 3 STEP 2: IF MID$ (A$,Y,2) = MID$ ("INRI",Z,2) THEN CC = CC + 1000 + 8390 NEXT + 8400 IF MID$ (B$,X,2) < > "NA" THEN 8440 + 8410 FOR Z = 1 TO 7 STEP 2: IF MID$ (A$,Y,2) = MID$ ("AGASDEVA",Z,2) THEN CC = CC + 1000 + 8430 NEXT + 8440 IF MID$ (B$,X,2) < > "NI" THEN 8470 + 8450 IF MID$ (A$,Y,2) = "IN" THEN CC = CC + 1000 + 8460 IF MID$ (A$,Y,2) = "NI" THEN CC = CC - 1000 + 8470 IF MID$ (B$,X,2) = "PO" AND MID$ (A$,Y,2) = "PO" THEN CC = CC - 1000 + 8480 IF MID$ (B$,X,2) < > "RI" THEN 8520 + 8490 FOR Z = 1 TO 11 STEP 2: IF MID$ (A$,Y,2) = MID$ ("AGDEHIINNARI",Z,2) THEN CC = CC + 1000 + 8510 NEXT + 8520 IF MID$ (B$,X,2) < > "VA" THEN 8560 + 8530 FOR Z = 1 TO 5 STEP 2: IF MID$ (A$,Y,2) = MID$ ("ASINVA",Z,2) THEN CC = CC + 1000 + 8550 NEXT + 8560 IF MID$ (B$,X,2) < > "WA" THEN 8600 + 8570 FOR Z = 1 TO 5 STEP 2: IF MID$ (A$,Y,2) = MID$ ("INRIWA",Z,2) THEN CC = CC + 1000 + 8590 NEXT + 8600 REM + 8610 NEXT + 8620 NEXT :TR = VAL ( MID$ (B$,3,1)): IF TR = 0 AND MID$ (B$,3,1) = "0" THEN TR = 0: GOTO 8640 + 8635 TR = ASC ( MID$ (B$,3,1)) - 55: IF TR > 19 THEN TR = TR - 1: IF TR > 24 THEN TR = TR - 1 + 8640 TT = (TR - TL) * .1: IF TT = < - 1 THEN CC = 0: GOTO 8670 + 8660 CC = CC + (CC * TT) + 8670 IF CC < 0 THEN CC = 0 + 8680 RETURN + 9000 DM = (T1 - T2) + ( - 3 * (P2 < 5)) + (3 * (P2 > 7)) + (TZ * - 6):PH = 0:PM = 0:PL = 0:CG = 0: ON P1 GOTO 9060,9070,9080,9090,9100,9110,9120,9130,9140,9150 + 9050 GOTO 9160 + 9060 PM = FN A(6) + DM - 2:PL = FN B(6) + DM - 6: GOTO 9160 + 9070 PH = FN A(6) + DM - FN A(6):PM = FN A(6) + DM:PL = FN B(6) + DM: GOTO 9160 + 9080 PH = FN B(6) + DM - FN B(6):PM = FN B(6) + DM - FN A(7):PL = FN B(6) + DM: GOTO 9160 + 9090 PH = FN B(6) + DM - FN A(6):PM = FN B(6) + DM - FN A(7):PL = FN C(6) + DM - FN A(5): GOTO 9160 + 9100 PH = FN B(6) + DM - FN A(6):PM = FN C(6) + DM - FN B(7):PL = FN C(6) + DM - FN A(5): GOTO 9160 + 9110 PH = FN C(6) + DM - FN B(6):PM = FN C(6) + DM - FN B(7):PL = FN C(6) + DM: GOTO 9160 + 9120 PH = FN C(6) + DM - FN B(6):PM = FN C(6) + DM - FN A(7):PL = FN C(6) + DM: GOTO 9160 + 9130 PH = FN C(6) + DM - FN A(6):PM = FN C(6) + DM - FN A(7):PL = FN B(6) + FN B(8) + DM: GOTO 9160 + 9140 PH = FN C(6) + DM - FN A(6):PM = FN C(6) + DM:PL = FN B(6) + FN B(8) + FN A(5) + DM: GOTO 9160 + 9150 PH = FN C(6) + DM:PM = FN B(6) + FN B(5) + DM:PL = FN B(6) + FN B(8) + FN B(5) + DM: GOTO 9160 + 9160 PH = PH + V1:PM = PM + V2:PL = PL + V3: IF PH < 0 THEN PH = 0 + 9170 IF OP > 8 OR OP < 7 THEN PH = 0:PM = 0:PL = 0:CG = 0 + 9180 IF PM < 0 THEN PM = 0 + 9190 IF PL < 0 THEN PL = 0 + 9210 DM = (T1 - T2) + ( - 4 * (P2 < 5)) + (1 * (P2 > 7)):CG = 0:K1 = FN A(5):K2 = FN A(6):K3 = FN A(7): IF TZ = 2 THEN CG = 0: GOTO 9510 + 9240 IF TZ = 1 THEN ON P1 GOTO 9280,9300,9320,9340,9360,9380,9410,9430,9460,9490 + 9250 ON P1 GOTO 9270,9290,9310,9330,9350,9370,9400,9420,9450,9480 + 9260 CG = 0: GOTO 9510 + 9270 CG = 10 * (K1 + DM - 4) + 9280 CG = CG + 5 * (K2 + DM - 4 + V4): GOTO 9510 + 9290 CG = 10 * (K1 + DM - 2) + 9300 CG = CG + 5 * (K2 + DM - 1 + V4): GOTO 9510 + 9310 CG = 10 * (K1 + DM - 1) + 9320 CG = CG + 5 * (K2 + DM + V4): GOTO 9510 + 9330 CG = 10 * (K1 + DM) + 9340 CG = CG + 5 * (K2 + DM + 1 + V4): GOTO 9510 + 9350 CG = 10 * (K1 + DM + 1) + 9360 CG = CG + 5 * (K2 + DM + 2 + V4): GOTO 9510 + 9370 CG = 10 * (K1 + DM + 2) + 9380 CG = CG + 5 * (K2 + DM + 3 + V4):CG = CG + (K3 + DM - 3): GOTO 9510 + 9400 CG = 10 * (K1 + DM + 3) + 9410 CG = CG + 5 * (K2 + DM + 4 + V4):CG = CG + (K3 + DM - 3): GOTO 9510 + 9420 CG = 10 * (K1 + DM + 4) + 9430 CG = CG + 5 * (K2 + DM + 5 + V4):CG = CG + (K3 + DM - 2): GOTO 9510 + 9450 CG = 10 * (K1 + DM + 5) + 9460 CG = CG + 5 * (K2 + DM + 6 + V4):CG = CG + (K3 + DM - 2): GOTO 9510 + 9480 CG = 10 * (K1 + DM + 6) + 9490 CG = CG + 5 * (K2 + DM + 7 + V4):CG = CG + (K3 + DM) + 9510 IF CG < 0 THEN CG = 0 + 9520 RETURN + 10000 SP = 255: REM + 10001 HOME :FI$ = "SPINWARD": VTAB 4: PRINT "USE SECTOR: > ";FI$: VTAB 4: INPUT "USE SECTOR: > ";F$: IF F$ < > "" THEN FI$ = F$ + 10012 PRINT : PRINT "READING SECTOR...": PRINT CHR$ (4);"MONICO": PRINT CHR$ (4);"OPEN ";FI$;".MAP,L7": PRINT CHR$ (4);"READ ";FI$;".MAP,R0": INPUT R: DIM HX$(R),AV(15),PO(32,40),OD(13,13),FL(169),J(169),A$(169): FOR Z = 1 TO R: VTAB 15: PRINT CHR$ (4);"READ ";FI$;".MAP,R";Z: INPUT A$:X = VAL ( LEFT$ (A$,2)):Y = VAL ( MID$ (A$,3,2)):PO(X,Y) = Z + 10032 IF MID$ (A$,5,1) = "T" THEN PO(X,Y) = PO(X,Y) * ( - 1) + 10034 HX$(Z) = LEFT$ (A$,4): NEXT : PRINT CHR$ (4);"CLOSE": PRINT CHR$ (4);"NOMONICO":DA = 1:YR = 1107:DA$ = "001-1107": DEF FN A(N) = INT ( RND (5) * 6) + 1: DEF FN B(N) = FN A(N) + FN A(N): DEF FN C(N) = FN B(N) + FN A(N): DEF FN D(N) = FN C(N) + FN A(N):BL$ = "------------------------------------" + 10170 TEXT : HOME : PRINT FI$;" ";TI$;" ";NA$;: HTAB 30: PRINT " ";DA$: PRINT "0";BL$: PRINT CHR$ (4);"OPEN OD JUMP": PRINT CHR$ (4);"READ OD JUMP": FOR X = 1 TO 13: FOR Y = 1 TO 13: INPUT OD(X,Y): NEXT : NEXT : PRINT CHR$ (4);"CLOSE": PRINT CHR$ (4);"OPEN DATAFILE": PRINT CHR$ (4);"READ DATAFILE": INPUT HE$: FOR X = 0 TO 9: INPUT SE$(X): NEXT : FOR X = 1 TO 15: INPUT AV(X): NEXT : PRINT CHR$ (4);"CLOSE" + 20000 REM + 20010 HOME : GOSUB 3000: PRINT FI$;" ";TI$;" ";NA$;: HTAB 30: PRINT " ";DA$: PRINT "1";BL$: PRINT CHR$ (4);"OPEN SHIPS, L100": FOR X = 0 TO 25 STEP 2: PRINT CHR$ (4);"READ SHIPS, R";X + 1: INPUT A$: VTAB (X / 2) + 4: PRINT CHR$ (X + 65);" "; MID$ (A$,69,16): PRINT CHR$ (4);"READ SHIPS, R";X + 2: INPUT A$: VTAB (X / 2) + 4: HTAB 20: PRINT CHR$ (X + 66);" "; MID$ (A$,69,16): NEXT : PRINT CHR$ (4);"CLOSE" + 20150 PRINT : INPUT "SELECT YOUR SHIP? > ";A$:A$ = LEFT$ (A$ + "A",1):TY = ASC (A$) - 64: IF TY < 1 OR TY > 26 THEN 20150 + 20170 GOSUB 1500: IF A$ = "/" THEN 20000 + 20175 HOME : PRINT "SHIP CHARACTERISTICS": PRINT BL$: INPUT "SHIP NAME? > ";A$: IF A$ = "" THEN 20200 + 20190 NA$ = A$ + 20200 PRINT "CREW SKILLS: ": INPUT " STEWARD- ";A$: GOSUB 1000:V1 = VAL (A$):SA = SA + (V1 * 300): INPUT " ADMIN- ";A$: GOSUB 1000:V2 = VAL (A$): INPUT " STREETWISE- ";A$: GOSUB 1000:V3 = VAL (A$): INPUT " LIAISON- ";A$: GOSUB 1000:V4 = VAL (A$): INPUT "CREDIT BALANCE? > ";CR$:CR = VAL (CR$) + 20300 VTAB 13: PRINT "STARTPOINT? (0000) > ";HX$(SP) + 20310 VTAB 13: INPUT "STARTPOINT? (0000) > ";A$: IF A$ = "" THEN 20381 + 20320 A$ = RIGHT$ ("0000" + A$,4):X = VAL ( LEFT$ (A$,2)):Y = VAL ( RIGHT$ (A$,2)): IF Y < 1 OR Y > 40 OR X < 1 OR X > 32 THEN 20310 + 20360 IF PO(X,Y) < > 0 THEN SP = ABS (PO(X,Y)) + 20370 IF PO(X,Y) = 0 THEN PRINT "INVALID STARTPOINT.": GOTO 20300 + 20380 PRINT "NEW STARTPOINT: ";HX$(SP) + 20381 VTAB 15: PRINT "DATE? (000-0000) > ";DA$: VTAB 15: INPUT "DATE? (000-0000) > ";A$: IF A$ = "" THEN 20390 + 20383 DD = VAL ( LEFT$ (A$,3)): IF DD < 1 OR DD > 365 THEN 20381 + 20385 YR = VAL ( MID$ (A$,5)): GOSUB 3000: PRINT "DATE: ";DA$ + 20390 PRINT : PRINT "PROCESSING...":A = SP + 30020 X = FRE (X): HOME : GOSUB 3000: PRINT FI$;" ";TI$;" ";NA$;: HTAB 30: PRINT " ";DA$: PRINT "2";BL$: GOSUB 2000:XC = VAL ( LEFT$ (A$,2)):YC = VAL ( MID$ (A$,3,2)): PRINT "SYSTEM: "; LEFT$ (A$,14);:A$(0) = A$: HTAB 30: PRINT MID$ (A$,33): PRINT "OVERHEAD: "; INT (OH);" (MAX= ";OV;"). ": PRINT "CR BALANCE: "; INT (CR);: IF UF > 0 THEN PRINT " UNREFINED FUEL."; + 30120 PRINT :A1$ = A$(0): IF MSG = 1 AND CG$ = HX$(A) THEN PRINT "MESSAGE DELIVERED.":MSG = 0:BB$ = "":CG$ = "" + 30150 IF OP = 5 AND MSG = 1 THEN PRINT "MESSAGE TO: ";BB$ + 30160 IF OP = 6 THEN PRINT XR;" UNSURVEYED WORLDS." + 30180 GOSUB 7000: IF B < > 0 THEN PRINT "CARGO: ";CG$: GOTO 30220 + 30200 PRINT "CARGO HERE: ";CA$:B$ = CA$ + 30220 PRINT "FARES RCVD: ";(PH * 10000) + (PM * 8000) + (PL * 1000) + (CG * 1000): PRINT "FARES- HI "; SPC( PH < 10);PH;" MD "; SPC( PM < 10);PM;" LO "; SPC( PL < 10);PL;" CG "; SPC( CG < 10); SPC( CG < 100);CG: VTAB 11: PRINT "--------------DESTINATIONS-------------": GOSUB 6000 + 30260 VTAB 12: PRINT " # HEX SHGZB AL PRICE PROFIT FARES?": PRINT "--";BL$: IF FL = 0 THEN PRINT "YOUR SHIP CAN'T REACH ANY WORLDS.": END + 30280 PRINT CHR$ (4);"OPEN ";FI$;",L50" + 30290 I = 1:I1 = 1 + 30300 PRINT CHR$ (4);"READ ";FI$;",R";FL(I): INPUT A1$: PRINT CHR$ (4):XPL = 0: IF MID$ (A1$,42,1) = "*" OR MID$ (A1$,16,1) = "S" OR MID$ (A1$,16,1) = "W" OR MID$ (A1$,16,1) = "A" OR MID$ (A1$,16,1) = "B" THEN XPL = 1 + 30350 E$ = MID$ (A1$,6,1):F$ = " ": IF VAL ( MID$ (A1$,9,1)) > 0 AND MID$ (A1$,8,1) > "1" THEN F$ = "O" + 30380 IF VAL ( MID$ (A1$,9,1)) > 0 AND MID$ (A1$,8,1) < "2" THEN F$ = "I" + 30390 E$ = E$ + F$ + MID$ (A1$,38,1) + MID$ (A1$,36,1) + MID$ (A1$,16,1) + " " + MID$ (A1$,33,2) + " ": GOSUB 4000: IF OP = 5 AND MSG = 0 AND ( MID$ (A1$,16,1) = "N" OR MID$ (A1$,16,1) = "A") THEN MSG = 1:BB$ = HX$( INT ( RND (R) * R) + 1) + 30420 IF OP = 9 OR OP = 5 OR OP = 6 THEN 30470 + 30430 GOSUB 7000: IF B < > 0 THEN CC = VAL ( MID$ (CG$,23)):B$ = CG$ + 30450 GOSUB 8000: GOSUB 9000 + 30470 A$(I) = A$:CA = VAL ( MID$ (B$,23)): VTAB I1 + 13: PRINT SPC( I < 10);I;". ";: PRINT HX$(FL(I));" ";: IF OP = 6 AND XPL = 0 THEN PRINT " UNSURVEYED.": GOTO 30670 + 30530 PRINT E$;: IF SL$ = "U" AND ( MID$ (A1$,6,1) > "C" AND MID$ (A1$,38,1) < > "G") THEN PRINT "INACCESSIBLE.": GOTO 30680 + 30550 IF OP > 7 AND MID$ (A1$,40,1) = " " THEN PRINT "NOT A TRADEWORLD.": GOTO 30680 + 30560 IF OP = 5 AND MSG = 1 AND HX$(FL(I)) = BB$ THEN PRINT "MESSAGE ADDRESSEE.": GOTO 30670 + 30570 IF OP = 9 OR OP = 5 OR OP = 6 THEN PRINT " ": GOTO 30670 + 30580 G$ = RIGHT$ (" " + STR$ ( INT (CC)),6): HTAB 19: PRINT G$;:G$ = RIGHT$ (" " + STR$ ( INT (CC - CA)),6): HTAB 25: PRINT G$;" ";: IF PH > SR - CW THEN PH = SR - CW + 30620 IF PM > SR - (CW + PH) THEN PM = SR - (CW + PH) + 30630 IF PL > LP THEN PL = LP + 30640 IF CG > CH THEN CG = CH + 30650 PF = (PH * 10000) + (PM * 8000) + (PL * 1000) + (CG * 1000): HTAB 33: PRINT SPC( PF < 10); SPC( PF < 100); SPC( PF < 1000); SPC( PF < 10000); SPC( PF < 100000); INT (PF) + 30670 GOTO 30710 + 30680 PRINT CHR$ (4): IF I = FL THEN 30760 + 30700 IF FL(I + 1) = 0 THEN 30760 + 30710 IF I = FL THEN 30760 + 30720 IF I1 < 6 THEN I1 = I1 + 1:I = I + 1: GOTO 30300 + 30730 VTAB 21: INPUT "SHOW MORE? (Y/N) > ";A$: GOSUB 1000: IF A$ < > "Y" THEN 30760 + 30750 I1 = 1:I = I + 1: GOTO 30300 + 30760 VTAB 21: INPUT "WHAT DESTINATION? > ";A$: IF A$ = "A" THEN 30290 + 30780 IF A$ = "" THEN 30760 + 30790 DE = VAL (A$): IF DE > FL OR DE < 1 THEN 30730 + 30800 JF = J(DE):DE = FL(DE): VTAB 11: HTAB 33: PRINT HX$(DE): IF OP = 9 OR OP = 5 THEN DA = DA + 1: GOTO 31230 + 30830 IF OP = 6 THEN DA = DA + 7: GOTO 31230 + 30850 A = DE: GOSUB 2000:A1$ = A$: GOSUB 4000: GOSUB 9000: IF PH > SR - CW THEN PH = SR - CW + 30910 IF PM > SR - (CW + PH) THEN PM = SR - (CW + PH) + 30920 IF PL > LP THEN PL = LP + 30930 IF CG + B > CH THEN CG = CH - B + 30940 VTAB 21: INPUT "BOARD PASSENGERS & FREIGHT? > ";A$: GOSUB 1000: IF A$ = "W" THEN INPUT "WAIT HOW MANY DAYS? > ";A$: GOSUB 1000:DA = DA + VAL (A$): GOTO 30940 + 30942 IF A$ = "N" THEN PH = 0:PM = 0:PL = 0:CG = 0: GOTO 31000 + 30944 IF A$ = "P" THEN CG = 0 + 30946 IF A$ = "F" THEN PH = 0:PM = 0:PL = 0 + 30950 PF = (PH * 10000) + (PM * 8000) + (PL * 1000) + (CG * 1000): IF MID$ (SH$,89,1) = "S" THEN CR = CR + INT (PF / 2): GOTO 30980 + 30970 CR = CR + PF + 30980 PRINT "FARES= ";PF;: IF MID$ (SH$,89,1) = "S" THEN PRINT " LESS 50% FOR SUBSIDY."; + 30990 PRINT + 31000 VTAB 23: PRINT "HI: ";PH;" MID: ";PM;" LOW: ";PL;" CARGO: ";CG;" TONS.": IF B < > 0 THEN 31200 + 31020 IF CR < CC THEN 31200 + 31030 IF CG + B = CH THEN 31200 + 31040 VTAB 21: CALL - 868: INPUT "BUY GOODS? > ";A$: GOSUB 1000: IF A$ < > "Y" THEN 31220 + 31050 IF A$ = "Y" THEN VTAB 21: CALL - 868: INPUT "HOW MANY TONS? > ";A$ + 31060 IF A$ = "" THEN A$ = "9999" + 31070 BC = VAL (A$): IF BC < 1 THEN BC = 0: GOTO 31190 + 31080 BA = CH - CG:A1$ = A$(0): GOSUB 7000:BB = INT (CR / CC): IF (BC > BA) THEN BC = BA + 31130 IF BC > BB THEN BC = BB + 31140 B$ = A$:CG$ = B$:CW$ = A$(0):CR = CR - (BC * CC): VTAB 21: HTAB 20: PRINT " ";BC;" FOR ";(BC * CC) + 31190 HTAB 20: INPUT "ADVANCE DELIVERY? > ";A$: GOSUB 1000: IF A$ = "Y" THEN CR = CR - (.2 * (BC * CC)):DA = DA + 3: GOTO 31230 + 31200 REM + 31210 IF PM = 0 AND PH = 0 AND PL = 0 AND CG = 0 AND BC = 0 THEN INPUT "LEAVE IMMEDIATELY? > ";A$: GOSUB 1000: IF A$ = "Y" THEN DA = DA + 1: GOTO 31230 + 31220 DA = DA + 5 + 31230 REM + 31240 A = DE:XF = VAL ( LEFT$ (A1$,2)):YF = VAL ( MID$ (A1$,3,2)):FY = FY - ((JF * TN / 10) + (10 * PN)): IF FY < 0 AND MID$ (B$,5,5) = "HI IN" THEN FY = FY + B:B$ = " ":B = 0 + 31290 DA = DA + 9:A = DE: GOSUB 2000:XC = VAL ( LEFT$ (A$,2)):YC = VAL ( MID$ (A$,3,2)):A$(0) = A$: IF SE = 1 OR SE = 2 THEN 40000 + 31370 Z1 = FN B(5) + (UF > 0) + (MNT > 0): IF Z1 < 13 THEN 40000 + 31380 PRINT "MISJUMP (";Z1;"): ";:X = INT ( RND (6) * 32) + 1:Y = INT ( RND (4) * 40) + 1:A = PO(X,Y): IF A = 0 THEN PRINT NA$;" IS LOST IN DEEP SPACE (HEX ";X;Y;"). ALL CARGO, CREW, AND PASSENGERS ARE LOST." + 31420 A = ABS (A): IF A < > 0 THEN 31440 + 31430 IF A < > 0 THEN PRINT "SHIP IS THROWN TO "; LEFT$ (A$,4);"." + 31440 INPUT "CONTINUE? > ";Z$: IF DE < > A AND LEFT$ (Z$ + " ",1) = "I" THEN 40000 + 31460 DE = A: IF A = 0 THEN END + 40000 REM + 40010 CR = CR - ((CW + PH + PM) * 2000) + (LP * 100): HOME : GOSUB 3000: VTAB 1: PRINT FI$;" ";TI$;" ";NA$;: HTAB 30: PRINT " ";DA$: PRINT "3";BL$: PRINT "LIFE SUPPORT COSTS: ";((CW + PH + PM) * 2000) + (LP * 100): PRINT "FUEL USED: ";FU - FY:A = DE:XL = 1: GOSUB 2000:XL = 0:A$ = A$(0): PRINT "SYSTEM: "; LEFT$ (A$,14); + 40140 HTAB 30: PRINT MID$ (A$,33,2);" "; MID$ (A$,36,1): IF OP = 9 AND MID$ (A$,40,1) < > " " THEN PRINT "XBOAT TENDER REFUELS SHIP.":FY = FU:DA = DA + 1: GOTO 40440 + 40160 IF ( MID$ (A$(0),16,1) = "S" OR MID$ (A$(0),16,1) = "W" OR MID$ (A$(0),16,1) = "A" OR MID$ (A$(0),16,1) = "B") AND SE = 2 THEN PRINT "SCOUT BASE REFUELS SHIP.":FY = FU: GOTO 40440 + 40170 IF ( MID$ (A$(0),16,1) = "N" OR MID$ (A$(0),16,1) = "D" OR MID$ (A$(0),16,1) = "A" OR MID$ (A$(0),16,1) = "B") AND SE = 1 THEN PRINT "NAVAL BASE REFUELS SHIP.":FY = FU: GOTO 40440 + 40180 PRINT "GAS GIANT: ";:C$ = "ABSENT.":GG = 0: IF MID$ (A$(0),38,1) = "G" THEN C$ = "PRESENT.":GG = 1 + 40190 PRINT C$;: IF SL$ = "U" THEN PRINT : GOTO 40270 + 40210 HTAB 22: PRINT "OCEANS: ";:C$ = "ABSENT. ":HY = 0: IF ASC ( MID$ (A$(0),9,1)) > 48 AND ASC ( MID$ (A$(0),8,1)) < 50 THEN C$ = "ICE-CAPPED.":HY = 2 + 40250 IF ASC ( MID$ (A$(0),9,1)) > 48 AND VAL ( MID$ (A$(0),8,1)) > 1 THEN C$ = "PRESENT. ":HY = 1 + 40260 PRINT C$ + 40270 IF GG = 1 THEN INPUT "SKIM GAS GIANT? > ";A$ + 40280 GOSUB 1000: IF A$ = "Y" THEN DA = DA + 2:FY = FU:UF = UF + 1: GOTO 40430 + 40290 IF HY = 1 AND SL$ < > "U" THEN INPUT "OCEAN REFUEL? > ";A$ + 40300 GOSUB 1000: IF A$ = "Y" THEN DA = DA + 1:FY = FU:UF = UF + 1: GOTO 40430 + 40310 IF HY = 2 THEN INPUT "ICECAP REFUEL? > ";A$ + 40320 GOSUB 1000: IF A$ = "Y" THEN DA = DA + 4:FY = FU:UF = UF + 1: GOTO 40430 + 40330 IF FY > = FU THEN 40440 + 40340 RF = 0: IF MID$ (A$(0),6,1) = "A" OR MID$ (A$(0),6,1) = "B" THEN RF = 1 + 40350 IF RF = 1 THEN PRINT "REFINED AND "; + 40360 PRINT "UNREFINED FUEL AVAILABLE.": IF MID$ (SH$,28,1) = "U" AND MID$ (A$(0),6,1) > "C" THEN PRINT "SURFACE REFUELLING FACILITIES ARE INACCESSIBLE. REFUELLING TAKES 14 DAYS.":DA = 14: GOSUB 3000:UF = UF + 1:FY = FU: GOTO 40440 + 40380 INPUT "REFUEL WITH (R/U) > ";A$:A$ = LEFT$ (A$ + "R",1): IF A$ = "R" AND RF = 0 THEN A$ = "U" + 40400 IF A$ = "R" THEN CF = (FU - FY) * 500:FY = FU:UF = UF - 1 + 40410 IF A$ = "U" THEN CF = (FU - FY) * 100:FY = FU:UF = UF + 1 + 40420 IF CF < > 0 THEN PRINT "BOUGHT CR";CF;" OF FUEL." + 40430 IF UF < 1 THEN UF = 0 + 40440 PRINT :B = BC: IF OP < > 7 THEN 50000 + 40480 PRINT CHR$ (4);"OPEN ";FI$;", L50": PRINT CHR$ (4);"WRITE ";FI$;", R";DE: PRINT LEFT$ (A$(0),41);"* ": PRINT CHR$ (4);"CLOSE" + 50000 REM + 50001 IF B < 1 THEN 50350 + 50010 VTAB 11: GOSUB 3000: PRINT FI$;" ";TI$;" ";NA$;: HTAB 30: PRINT " ";DA$: PRINT "4";BL$:B$ = CG$:A1$ = A$(0): GOSUB 7000: GOSUB 8000: PRINT B;" TONS OF ";: PRINT B$: PRINT "BASE COST: "; MID$ (B$,19);: HTAB 21: PRINT "BASE PRICE: ";CC:CB = VAL ( MID$ (B$,23)): INPUT "SELL GOODS? > ";A$: GOSUB 1000: IF A$ < > "Y" THEN 50420 + 50140 BR = ASC ( MID$ (A$(0),6,1)) - 64:BR = 5 - BR: IF BR < 1 THEN PRINT "NO BROKERS AVAILABLE.":BR = 0: GOTO 50230 + 50170 IF BR = 1 THEN PRINT "BROKER-1 AVAILABLE." + 50180 IF BR > 1 THEN PRINT "BROKER-1 TO ";BR;" AVAILABLE." + 50190 INPUT "USE A BROKER? > ";A$: GOSUB 1000: IF LEFT$ (A$,1) = "Y" THEN INPUT "WHICH NUMBER? > ";A$ + 50210 IF VAL (A$) < 0 OR VAL (A$) > BR THEN 50190 + 50220 BR = VAL (A$) + 50230 A$ = A$(0): PRINT B;" TONS AT CR";CB;" BASE COST.": GOSUB 5000:E = INT (100 * CD / CB): IF E = 100 THEN PRINT "SOLD AT NO PROFIT.": GOTO 50300 + 50280 IF E < 100 THEN PRINT "SOLD AT ";100 - E;"% LOSS.": GOTO 50300 + 50290 IF E > 100 THEN PRINT "SOLD AT ";E - 100;"% PROFIT.": GOTO 50300 + 50300 PRINT "BROKER COMMISSION: ";BR * 5;"%.": PRINT "PROCEEDS: ";CC;" ("; INT (CC / B);" PER TON).":CR = CR + CC:B$ = "":B = 0:BC = 0 + 50350 IF MNT < 1 THEN 50410 + 50360 PRINT FI$;" ";TI$;" ";NA$;: HTAB 30: PRINT " ";DA$: PRINT "6";BL$: IF MNT > 0 THEN PRINT : PRINT "THE SHIP NEEDS ANNUAL MAINTENANCE." + 50375 IF OP = 5 AND ( MID$ (A$(0),26,1) = "B" OR MID$ (A$(0),26,1) = "W") THEN 50380 + 50377 IF ST < 3 THEN 50380 + 50379 GOTO 50400 + 50380 INPUT "PERFORM IT NOW? > ";A$: GOSUB 1000: IF A$ = "Y" THEN DA = DA + 14:MNT = 0: PRINT "MAINTENANCE COST: ";((CST * 1E + 6) * .001) + 50400 REM + 50410 VTAB 23: INPUT "CONTINUE? > ";Z$ + 50420 OH = (LP * 100) + ((PH + PM + CW) * 2000) + (SAL * .5) + 100 + ((.001 / 24) * 1E + 6 * CST) + (SAL / 24):CR = CR - OH: GOTO 30020 diff --git a/samples/sample.adventure.txt b/samples/sample.adventure.txt new file mode 100644 index 0000000..95c3e44 --- /dev/null +++ b/samples/sample.adventure.txt @@ -0,0 +1,254 @@ +100 DIM INW$(10):DIM INPTK(10):DIM VOCAB$(60):DIM NULLW$(4):DIM IDESC$(30) +140 DIM ILOC(30):DIM RNAME$(31):DIM RDESC$(31):DIM REXIT(31,6):DIM EXDESC$(10): DIM EXLOC(10,2) +180 SAFED = 0: LOC=1: IC = 0 +190 SP = 0 +300 DATA "7UVYAO5", "2UQWVJ3", "2GCUV1", "7DLZA3", "9DY5", "5ITBS2", "6T8", "2U3", "2G9", "2Y7", "8C5", "8L8" +305 DATA "2K3", "1JOWFOUPSZ8", "1TDPSF0", "8RCUX6", "3KHOS7" +310 DATA "4XEOI3", "7KYVW9", "6RUUQ9", "3UHDG4", "9NGJVRWN9", "5ZSQTHP0", "9NJC8", "6YVOT4" +312 DATA "9VXEN1", "8WXMV6", "9CRN6", "4SMP8", "9YDC9", "8TMNB9", "5HJSYJW9", "4VMKLX2" +400 DATA "5SJBXUFUJW3", "6ZKJJEHKGX0", "7MBZL7", "1KBDL1", "7WPJABYL0", "1CVOHFF8" +405 DATA "9TNH3", "2VQR3", "6TUZK0", "8OIQVMAJCZOMZ4", "7NSVCLZ4", "1CPYTQSJOH0" +410 DATA "4FVEGI9", "4QEKEDMRI8", "4SMPGER8", "2EJGEMDQQM9", "6JOGSUTJ8", "2NQXGTDQA6" +415 DATA "7PUCLZATLUA1", "9UXXWB5", "4JVMHKI3", "4GSYGL0", "2ENQVJGU0", "3GRRU8" +420 DATA "8ZIQTQVO8", "3GXPEZDLWHU6", "6LAYKHUD0", "1UIF5", "8BW3", "8EQBP6", "7BZPUN0" +451 DATA "8...BIGA PWCAM CVTQSMTG MDMZ BW JM AWTL. BITMA WN OCBBML ABIQZEMTTA IVL JWWJG BZIXA PIDM AXWWSML JCGMZA...8" +452 DATA "4WSQISRI LEW FIIR TPECMRK ZIVC VSYKL AMXL XLMW XSC3", "3ROG-IDVKLRQHG HOHFWULFDO IXVH5" +454 DATA "2VKTG LCEM HQT NKHVKPI JGCXA QDLGEVU NKMG ECTU8", "6ATIRK ZGEY OT GRR NOY YGRRUC MRUXE5" +456 DATA "3FRUG IRU EXQJHH MXPSLQJ3", "2C UOCNN DTCUU MGA4", "5F HMNQI'X YTD6", "2VJG YTKVKPI KU TGXGTUGF7" +458 DATA "5XZUUTXJIQD ITL KTTI, YMTZLM NY FUUJFWX YT GJ RFIJ TK UQFXYNH4" +459 DATA "1SVCCFS HMPWFT VTFE GPS DMFBOJOH7", "1B RVFFO-TJAFE CPYTQSJOH0", "7H IHJR IYHJL7" +460 DATA "5...YFDX' XYWFSLJ NSAJSYNTSX NSHQZIJ GTTGD-YWFUUJI ITTWX FSI YTDX YMFY TUJS ITTWX GD WJRTYJ HTSYWTQ...6" +462 DATA "1UIJT DBO DPOUBJOT GJOF MVCSJDBUJOH PJM7", "9DWLUN CJHB' LQNLTKXXT URBCB J KJUJWLN XO $220,0004" +464 DATA "3WKLV GLDPRQG'V EHDXWB VWHPV IURP DOO WKH JRGGDPQHG PRQHB LW LV ZRUWK9" +466 DATA "1MPWFSCPZ'T GJSTU BMCVN JO WJOZM, XPSUI BO JODBMDVMBCMF TVN8" +467 DATA "9YAN-RYX BQJANB XO JYXUUX LXVYDCRWP QJEN CX KN FXACQ ... BXVNCQRWP5" +468 DATA "4E XLMGO AEH SJ GEREHMER RSXIW7" +470 DATA "4XLMW SPH VIJVMKIVEXSV'W QSXSV PEFSVW LIEZMPC8", "3DQ RYHUVWXIIHG, GXVWB FRXFK7" +472 DATA "3D GLVJXVWLQJ SLOH RI VRLOHG ODXQGUB2", "", "", "" +473 DATA "3DQ ROG-IDVKLRQHG IXVHERA. WKH IXVH PDUNHG 'DWWLF' LV PLVVLQJ.8" +502 DATA "5KTDJW9", 2, 31, 3, 4, 0, 0, "1UIF FOUSZXBZ UP UIF IPVTF4" +504 DATA "1LJUDIFO8", 0, 1, 0, 0, 0, -1 +505 DATA "7JVBUALYAVWZ HYL KBZAF HUK AOLYL HYL YBZAPUN WVAZ HUK WHUZ7" +506 DATA "3VLWWLQJ URRP3", 2, 0, 11, 1, 12, 0 +507 DATA "2VJKU TQQO KU VYQ UVQTKGU JKIJ CPF EQPVCKPU GNGICPV EJCKTU CPF EQWEJGU1" +508 DATA "9QJUUFJH0", 6, 7, 1, 5, 0, 0, "9J WJAAXF QJUUFJH FQRLQ ADWB FNBC XO CQN OXHNA3" +510 DATA "8PITTEIG0", 0, 9, 4, 10, 0, 0, "2C PCTTQY JCNNYCA CV VJG YGUV GPF QH VJG JQWUG2" +512 DATA "9MNW5", 0, 4, 0, 0, 0, 0, "7AOPZ YVVT OHZ HU HUJPLUA ALSLCPZPVU6" +514 DATA "7IHAOYVVT4", 4, 0, 0, 0, 0, -1, "2C FKPIA DCVJTQQO YKVJ C ETCEMGF UKPM1" +516 DATA "1MJCSBSZ3", 0, 0, 0, 24, 0, 0 +517 DATA "2VJKU YGNN-HWTPKUJGF NKDTCTA KU NKPGF YKVJ DQQMU CPF NGCVJGT HWTPKVWTG7" +518 DATA "4WQEPP FIHVSSQ7", 5, 0, 0, 0, 0, 0 +519 DATA "7AOPZ ZTHSS ILKYVVT OHZ H ADPU ILK HUK JOHPY. PA SVVRZ SPAASL BZLK.5" +520 DATA "1HBSBHF3", 0, 0, 5, 0, 0, 0 +521 DATA "4XLI GEZIVRSYW KEVEKI LSPHW E RSR-STIVEXMSREP KVIQPMR ERH TMPIW SJ NYRO9" +522 DATA "7KPUPUN YVVT8", 0, 0, 0, 3, 0, 0 +523 DATA "2VTQRJKGU NKPG VJG YCNNU. VJGTG CTG UKZ EJCKTU CTQWPF C NQPI VCDNG.4" +524 DATA "5GFQHTSD0", 13, 0, 0, 14, -1, 3 +525 DATA "2DCNEQPA CDQXG VJG UKVVKPI TQQO. C TCKNKPI RTQVGEVU AQW HTQO C 15-HQQV FTQR.1" +526 DATA "3PDVWHU EHGURRP0", 0, 12, 0, 0, 0, 0 +527 DATA "9CQRB UJAPN LXAWNA KNMAXXV QJB BXURM FJUWDC ODAWRCDAN JWM J UJAPN VRAAXA8" +528 DATA "4LEPPAEC0", 0, 15, 12, 17, 0, 0, "2C JCNNYCA YKVJ C NCTIG CTEJ QP KVU UQWVJ UKFG8" +530 DATA "3JDPH URRP9", 14, 0, 0, 16, 0, 0 +531 DATA "6ZNOY KRKMGTZ MGSK XUUS NGY G VUUR ZGHRK GTJ SGXHRK INKYYHUGXJ2" +532 DATA "8KTWAMB8", 0, 0, 15, 0, 0, 0, "8I AXIKQWCA KTWAMB WNN BPM OIUMZWWU1" +534 DATA "8PITTEIG0", -1, 0, 14, -1, 0, 0, "6G NGRRCGE OT ZNK IKTZKX UL ZNK YKIUTJ LRUUX4" +536 DATA "3FKLOG'V URRP6", 0, 17, -1, 0, 0, 0 +537 DATA "5DTZW HTZXNS'X WTTR NS MFUUNJW YNRJX, GJKTWJ MJ WFS TKK YT OTNS YMJ GFFYM UFWYD2" +538 DATA "7ZLJYLA YVVT1", 0, 0, 0, 18, 0, 0, "5F IFWP HMFRGJW TKK YMJ GJIWTTR7" +540 DATA "1EBOHFSPVT IBMM9", 21, 22, 17, -1, 0, 0 +541 DATA "5YMNX JJWNJ MFQQ MFX YMWJJ NIJSYNHFQ ITTWX TS YMJ BJXY BFQQ2" +542 DATA "9LXAWNA KNMAXXV7", 0, 20, 0, 0, 0, 0, "6G IUFE IUXTKX XUUS COZN COTJUCY UT ZCU CGRRY9" +544 DATA "3EDWKURRP4", 20, 0, 0, 0, 0, 0, "7HU LSLNHUA IHAO DPAO H TPYYVY VCLY H THYISL ZPUR3" +546 DATA "3GXPEZDLWHU6", 0, 0, 20, 0, 0, -1, "8I KZIUXML LCUJEIQBMZ9" +548 DATA "7KBTIDHPALY6", 0, 0, 8, 0, 23, 0, "2C ETCORGF FWODYCKVGT9" +550 DATA "3DWWLF3", 0, 0, 0, 0, 0, 12, "7H KBZAF HAAPJ DPAO SVD ZSVWPUN DHSSZ2" +552 DATA "1TUPSBHF SPPN0", 0, 0, 27, 0, 0, 0 +553 DATA "2C DCTG TQQO WUGF VQ UVQTG TCPFQO GSWKROGPV CPF HWTPKVWTG3" +554 DATA "5QFZSIWD3", 0, 0, 28, 26, 0, 0 +555 DATA "6ZNOY XUUS NGY G CGYNKX GTJ JXEKX, GY CKRR GY G HUORKX GTJ LAXTGIK4" +556 DATA "7DVYRYVVT0", 0, 0, 29, 27, 0, 0, "5JVZNURJSY KTW BTWPNSL BTTI FSI RJYFQ7" +558 DATA "6HUZZUS UL YZGOXY8", 0, 0, 0, 28, -1, 0, "2UVCKTU HTQO DCUGOGPV VQ MKVEJGP0" +560 DATA "5RNI-FNW8", 0, 0, 0, 0, 0, 0, "2JCPIKPI HTQO C DWPIGG EQTF5" +562 DATA "5QJFAJ YMJ MTZXJ (FSI YMJ LFRJ)6", 0, 0, 0, 0, 0, 0, "" +650 DATA 1, -1, -1, 10, 30, 10, 13, 15, 9, 16, 22, 26, 25, 25, 28, 8, -1, 19, 21, 27 +655 DATA 2, 6, 7, -1, 12, -1, -1 +700 DIROFF = 30: ITEMOFF = 33: LASTITEM = 27: IMMOFF = 20: LWRD = 60: NXDESC = 7 +705 PR#3 : TEXT : HOME : PRINT "LOADING..."; : SP = 1 +710 FOR I = 1 TO LWRD: READ D$: GOSUB 10000: VOCAB$(I) = D2$: NEXT +750 FOR I = 1 TO 4: READ D$: GOSUB 10000: NULLW$(I) = D2$: NEXT +780 FOR I = 1 TO LASTITEM: READ D$: GOSUB 10000: IDESC$(I) = D2$: NEXT +800 FOR I = 1 TO 31: READ D$: GOSUB 10000: RNAME$(I) = D2$ +810 FOR J = 1 TO 6: READ REXIT(I,J): NEXT +820 READ D$: GOSUB 10000: RDESC$(I) = D2$: NEXT +950 FOR I = 1 TO LASTITEM: READ ILOC(I): NEXT +1000 DATA 5, 6, "5YMJWJ NX F QTHPJI ITTW YT YMJ STWYM2", 8, 6, "9CQNAN RB J UXLTNM MXXA CX CQN BXDCQ0" +1005 DATA 2, 6, "8ABIQZA TMIL LWEV BW I KMTTIZ. AMDMZIT ABMXA PIDM KWTTIXAML, UISQVO BPM ABIQZKIAM CVCAIJTM.9" +1010 DATA 29, 5, "3VWDLUV OHDG XS. VHYHUDO VWHSV KDYH FROODSVHG, PDNLQJ WKH VWDLUFDVH XQXVDEOH.9" +1015 DATA 12, 5, "3GDUN VWDLUV OHDG XS WR WKH DWWLF4", 17, 4, "4E PSGOIH HSSV XS XLI AIWX MW PEFIPPIH 'IBXVIQI HERKIV'0" +1025 DATA 17, 1, "4CSYV YRGPI'W HSFIVQER FPSGOW E HSSVAEC XS XLI RSVXL0" +1050 FOR I = 1 TO NXDESC: READ EXLOC(I,1): READ EXLOC(I,2): READ D$: GOSUB 10000: EXDESC$(I) = D2$: NEXT +1060 SP = 0 : HOME +2000 GOSUB 15000 +2500 IF LOC = 30 THEN D$= "5... FSI XUWNSL GFHP1": GOSUB 11000: LOC = 12 +2525 IF LOC = 31 THEN GOTO 19900 +2510 PRINT RNAME$(LOC): PRINT RDESC$(LOC) +2530 FOR I = 1 TO 6: NEIGH = REXIT(LOC, I): IF NEIGH > 0 THEN PRINT VOCAB$(I) ; ": "; RNAME$(NEIGH) +2559 NEXT +2560 FOR I = 1 TO NXDESC: IF LOC = EXLOC(I,1) AND REXIT(EXLOC(I,1),EXLOC(I,2)) <= 0 THEN PRINT EXDESC$(I) +2569 NEXT +2570 IF LOC = 17 AND REXIT(17,1) > 0 THEN D$="3BRXU XQFOH'V GREHUPDQ LV VQRULQJ SHDFHIXOOB3": GOSUB 11000 +2580 IF LOC = 3 AND ILOC(6) = -12 THEN D$="9J KDWPNN LXAM MJWPUNB OAXV CQN AJRURWP JKXEN5": GOSUB 11000 +2582 IF LOC = 12 AND ILOC(6) = -12 THEN D$="8I JCVOMM KWZL LIVOTMA NZWU BPM ZIQTQVO0": GOSUB 11000 +2600 FOR I = 1 TO LASTITEM: IF ILOC(I) = LOC THEN PRINT "THERE IS A "; VOCAB$(I + ITEMOFF); " HERE" +2619 NEXT +2620 IF LOC = 2 AND ILOC(3) = -1 THEN D$= "6YUSKZNOTM OY HGXKRE BOYOHRK ATJKX ZNK LXOJMK5": GOSUB 11000 +2650 IF LOC = 3 AND ILOC(5) = 30 THEN D$= "5YMJWJ NX F UNHYZWJ MNLM ZU TS YMJ BFQQ6": GOSUB 11000 +4999 IF LOC = 30 THEN TURN1 = 1 +5000 IF TURN1 <> 1 AND LOC = 30 THEN D$= "1...BOE TQSJOH CBDL1": GOSUB 11000: LOC = 12: GOTO 2500 +5010 TURN1 = 0: INPUT "] "; I$: INWORD = 0: WIDX = 0 +5020 FOR C = 1 TO LEN(I$): C$ = MID$(I$,C,1): IF C$ = " " AND INWORD = 1 THEN INWORD = 0 +5060 IF C$ <> " " AND INWORD = 0 THEN WIDX = WIDX + 1: INW$(WIDX) = "": INWORD = 1 +5065 IF WIDX > 10 GOTO 5100 +5070 IF C$ <> " " THEN INW$(WIDX) = INW$(WIDX) + C$ +5099 NEXT +5100 CURTOK = 1: FOR TIDX = 1 TO WIDX +5115 ISNULLW = 0 +5120 FOR XN = 1 TO 4: IF INW$(TIDX) = NULLW$(XN) THEN ISNULLW = 1 +5135 NEXT +5137 IF ISNULLW = 1 THEN GOTO 5170 +5140 FOR CMDIDX = 1 TO LWRD: IF INW$(TIDX) = VOCAB$(CMDIDX) THEN INPTK(CURTOK) = CMDIDX: CURTOK = CURTOK + 1 +5160 NEXT CMDIDX +5170 NEXT TIDX +5180 NTOK = CURTOK - 1 +6000 COMM = INPTK(1): ON NTOK+1 GOTO 5000, 6050, 6400, 7100 +6049 D$ = "8GWC KIV'B LW BPIB9": GOSUB 11000: GOTO 5000 +6050 IF INPTK(1) >= 1 AND INPTK(1) <= 12 THEN GOTO 7000 +6070 IF COMM <= 20 THEN ON COMM-12 GOTO 6100, 6100, 6200, 6300, 6350, 6099, 6099, 2500 +6099 D$ = "9QDQ?9": GOSUB 11000: GOTO 5000 +6100 D$ = "7FVB HYL JHYYFPUN:6": GOSUB 11000 +6110 FOR I = 1 TO LASTITEM +6120 IF ILOC(I) = 0 THEN PRINT " "; VOCAB$(I+ITEMOFF) +6130 NEXT I +6199 GOTO 5000 +6200 GOSUB 9500: GOTO 5000 +6300 IF LOC <> 12 THEN D$= "4ALS EVI CSY, HEZMH PII VSXL?8": GOSUB 11000: GOTO 5000 +6320 IF ILOC(6) <> -12 THEN D$ = "4CSY JSVKSX CSYV TEVEGLYXI2": GOSUB 11000: GOTO 5000 +6330 D$= "9HXD KDWPNN XOO CQN KJULXWH...5": GOSUB 11000: LOC = 30: GOTO 2510 +6350 GOSUB 15000: GOTO 5000 +6400 ARG = INPTK(2) - ITEMOFF: IF ARG < 1 or ARG > LASTITEM THEN D$ = "6NAN?9": GOSUB 11000: GOTO 5000 +6430 IF COMM > 17 AND COMM <= 27 THEN ON COMM-17 GOTO 6500, 6600, 6700, 6700, 6700, 6800, 6900, 7600, 6950, 8200 +6499 D$ = "5MZM?9": GOSUB 11000: GOTO 5000 +6500 IF ILOC(ARG) = 0 THEN D$ = "5DTZ FQWJFID MFAJ NY6": GOSUB 11000: GOTO 5000 +6510 IF ILOC(ARG) = 30 AND LOC = 3 AND ARG = 5 THEN D$= "2KV'U VQQ JKIJ0": GOSUB 11000: GOTO 5000 +6520 IF ILOC(ARG) <> LOC THEN D$ = "5NY'X STY MJWJ3": GOSUB 11000: GOTO 5000 +6530 IF IC >= 8 THEN D$ = "1ZPV'SF DBSSZJOH UPP NVDI4": GOSUB 11000: GOTO 5000 +6540 IF ARG > IMMOFF THEN D$ = "3LW'V WRR KHDYB3": GOSUB 11000: GOTO 5000 +6559 IF LOC = 29 AND ARG = 12 THEN D$ = "5DTZ HFS'Y IT YMFY9": GOSUB 11000: GOTO 5000 +6530 IC = IC + 1: IF LOC = 30 AND ARG = 5 THEN D$ = "7AHRPUN AOL WPJABYL YLCLHSZ H MBZLIVE6": GOSUB 11000: ILOC(ARG) = 0: ILOC(IMMOFF+7) = 30: GOTO 2500 +6590 ILOC(ARG) = 0: PRINT VOCAB$(INPTK(2)); ": TAKEN": GOTO 5000 +6600 IF ILOC(ARG) <> 0 THEN D$= "9HXD JANW'C LJAAHRWP RC5": GOSUB 11000: GOTO 5000 +6630 IC = IC - 1: IF LOC = 17 AND ARG = 10 AND REXIT(17,1) <= 0 THEN D$= "7AOL KVN SVVRZ KPZNBZALK. THFIL FVB ZOVBSK LHA PA.6": GOSUB 11000: GOTO 6690 +6640 IF LOC = 17 AND ARG = 2 AND REXIT(17,1) <= 0 THEN D$= "4XLI HSK GLIAW LMW JEZSVMXI XSC ERH MW WSSR EWPIIT7": GOSUB 11000: ILOC(ARG) = -999: REXIT(17,1)=18: GOTO 2500 +6650 IF LOC = 29 AND ARG = 12 AND REXIT(29,5) <= 0 THEN D$= "3WKH ERAVSULQJ FRYHUV WKH JDS LQ WKH VWDLUV8": GOSUB 11000: ILOC(ARG) = -999: REXIT(29,5) = 2: REXIT(2,6) = 29: GOTO 2500 +6690 ILOC(ARG) = LOC: PRINT VOCAB$(INPTK(2)); ": DROPPED": GOTO 5000 +6700 ARG = INPTK(2) - ITEMOFF +6740 IF ILOC(ARG) <> 0 AND ILOC(ARG) <> LOC THEN D$= "9RC'B WXC QNAN3": GOSUB 11000: GOTO 5000 +6750 IF ARG = 9 AND (LOC = 13 OR LOC = 22) THEN GOSUB 8000: GOSUB 8050: GOTO 5000 +6755 IF IDESC$(ARG) = "" THEN PRINT "THERE'S NOTHING SPECIAL ABOUT THE "; VOCAB$(INPTK(2)): GOTO 5000 +6760 PRINT IDESC$(ARG): GOTO 5000 +6800 IF ILOC(7) <> 0 THEN D$ = "7FVB KVU'A OHCL H RLF!2": GOSUB 11000: GOTO 5000 +6820 IF LOC = 5 THEN D$= "2VJG MGA FQGUP'V HKV VJG NQEM8": GOSUB 11000: GOTO 5000 +6830 IF LOC = 17 THEN D$ = "3BRX XQORFN WKH GRRU. EHZDUH!4": GOSUB 11000: REXIT(17,4) = 20: GOTO 2500 +6899 D$ = "5MZM?9": GOSUB 11000: GOTO 5000 +6900 IF ILOC(ARG) <> 0 THEN D$= "7FVB KVU'A OHCL PA!1": GOSUB 11000: GOTO 5000 +6920 IF ARG <> 10 THEN D$= "7FVB JHU'A LHA AOHA!0": GOSUB 11000: GOTO 5000 +6930 D$= "7AOLYL DHZ H KPHTVUK OPKKLU PUZPKL AOL NHPULZIBYNLY5": GOSUB 11000: ILOC(ARG) = -2: ILOC(17) = 0: GOTO 2500 +6950 AIMM = ARG - IMMOFF +6960 IF AIMM >= 1 AND AIMM <= 4 THEN ON AIMM GOTO 6970, 6975, 6980 +6965 D$= "5DTZ HFS'Y IT YMFY9": GOSUB 11000: GOTO 5000 +6970 D$= "9RC'B CXX QNJEH OXA HXD CX VXEN1": GOSUB 11000: GOTO 5000 +6975 D$= "1ZPVS CBDL JT BDUJOH VQ7": GOSUB 11000: GOTO 5000 +6980 D$= "9CQJC BNNVB YXRWCUNBB JWM DWBJWRCJAH4": GOSUB 11000: GOTO 5000 +7000 GOARG = INPTK(1): IF GOARG > 6 THEN GOARG = GOARG - 6 +7010 IF REXIT(LOC, GOARG) > 0 THEN LOC = REXIT(LOC, GOARG): GOTO 2500 +7020 IF LOC = 12 AND GOARG = 5 THEN D$= "3BRX'UH DIUDLG RI WKH GDUN1": GOSUB 11000: GOTO 5000 +7025 IF LOC = 17 AND GOARG = 1 THEN D$= "7FVB ULCLY KPK SPRL AOHA KVN2": GOSUB 11000: GOTO 5000 +7030 IF LOC = 23 AND REXIT(23, 6) <= 0 THEN D$ = "8BPM LCUJEIQBMZ UMKPIVQAU QA KWZZWLML IVL EWV'B UWDM2": GOSUB 11000: GOTO 5000 +7099 D$= "9HXD LJW'C PX CQJC FJH3": GOSUB 11000: GOTO 5000 +7100 IF COMM < 23 OR COMM > 30 THEN GOTO 6899 +7120 ARG = INPTK(2) - ITEMOFF: IF COMM <> 27 AND ARG < 1 or ARG > LASTITEM THEN D$ = "3KXK?9": GOSUB 11000: GOTO 5000 +7130 IF COMM <> 23 AND COMM <> 29 AND ILOC(ARG) <> LOC AND ILOC(ARG) <> 0 THEN D$= "5NY'X STY MJWJ3": GOSUB 11000: GOTO 5000 +7140 ON COMM-22 GOTO 6800, 6899, 6899, 7200, 7400, 7500, 7700, 7800 +7200 IF ARG < IMMOFF THEN D$= "7FVB JHU QBZA AHRL AOHA7": GOSUB 11000: GOTO 5000 +7220 AIMM = ARG - IMMOFF: MVARG = INPTK(3) - ITEMOFF: IF AIMM < 1 OR AIMM > 3 THEN D$ = "8GWC KIV'B LW BPIB9": GOSUB 11000: GOTO 5000 +7230 IF ILOC(MVARG) <> 0 THEN D$ = "1ZPV EPO'U IBWF JU!1": GOSUB 11000: GOTO 5000 +7240 ON AIMM GOTO 7250, 7300, 7350 +7250 IF MVARG <> 4 OR ILOC(3) >= 0 THEN D$= "4CSY GER'X HS XLEX9": GOSUB 11000: GOTO 5000 +7260 D$= "5DTZ OFHP ZU YMJ KWNILJ FSI KNSI F KZXJ ZSIJW NY8": GOSUB 11000: ILOC(3)=LOC: GOTO 2500 +7300 IF MVARG <> 13 OR ILOC(2) >= 0 THEN D$ = "2AQW ECP'V FQ VJCV9": GOSUB 11000: GOTO 5000 +7310 D$="5DTZ RTAJ YMJ HTZHM FSI KNSI F YJIIDGJFW GJMNSI NY7": GOSUB 11000: ILOC(2)=LOC: GOTO 2500 +7350 IF MVARG <> 11 THEN D$ = "4CSY GER'X HS XLEX9": GOSUB 11000: GOTO 5000 +7360 D$="3PRYLQJ WKH FORWKHV UHYHDOV D ODXQGUB FKXWH WR WKH EDVHPHQW3": GOSUB 11000: REXIT(LOC,6) = 27: GOTO 2500 +7400 IF LOC <> 20 THEN D$ = "3KXK?9": GOSUB 11000: GOTO 5000 +7450 IF INPTK(3) - ITEMOFF <> IMOFF + 4 THEN D$ = "2JWJ?9": GOSUB 11000: GOTO 5000 +7460 DOORDIR = INPTK(2) - DIROFF: IF DOORDIR < 1 OR DOORDIR > 3 THEN D$ = "4LYL?9": GOSUB 11000: GOTO 5000 +7470 GOSUB 8025 +7480 IF DOORDIR = SAFED THEN D$= "1PQFOJOH UIF EPPS SFWFBMT B EVNCXBJUFS2": GOSUB 11000: REXIT(LOC, 4) = 23: GOTO 2500 +7490 IF INT(RND(2)) > 1 THEN D$= "4E WLSX VMRKW SYX! MX AEW AIPP-EMQIH XSS.2": GOSUB 11000: GOTO 19000 +7495 D$= "2CP KTQPKPI DQCTF UNCOU QPVQ AQWT JGCF0": GOSUB 11000: GOTO 19000 +7500 IF LOC <> 12 THEN D$ = "6EUA IGT'Z JU ZNGZ9": GOSUB 11000: GOTO 5000 +7520 IF INPTK(2) - ITEMOFF <> 6 THEN D$= "9HXD LJW'C CRN CQJC8": GOSUB 11000: GOTO 5000 +7530 IF INPTK(3) - ITEMOFF <> (IMOFF + 5) THEN D$= "9HXD LJW'C CRN CX CQJC1": GOSUB 11000: GOTO 5000 +7540 IF ILOC(6) <> 0 THEN D$ = "8GWC LWV'B PIDM QB!1": GOSUB 11000: GOTO 5000 +7550 D$= "1UJFE4": GOSUB 11000: ILOC(6) = -12: IC = IC - 1: GOTO 2500 +7600 IF ILOC(8) <> 0 THEN D$ = "3KXK?9": GOSUB 11000: GOTO 5000 +7610 IF LOC = 18 THEN D$= "1UIFSF JT B GMBTI PG MJHIU BOE B DSBDLJOH TPVOE. BO PQFOJOH BQQFBST JO UIF FBTU XBMM1": GOSUB 11000: REXIT(18, 3) = 19: GOTO 2500 +7620 INVERSE: D$= "7DOLL!7": GOSUB 11000: NORMAL: PRINT "": GOTO 5000 +7700 IF LOC <> 20 THEN D$ = "3BRX FDQ'W GR WKDW9": GOSUB 11000: GOTO 5000 +7705 IF ILOC(15) <> 0 THEN D$= "2AQW FQP'V JCXG CPA QKN4": GOSUB 11000: GOTO 5000 +7720 IF INPTK(2) - ITEMOFF <> IMOFF + 6 THEN D$ = "1IVI?9": GOSUB 11000: GOTO 5000 +7725 D$= "2VJG FWODYCKVGT OGEJCPKUO PQY TWPU UOQQVJNA3": GOSUB 11000: REXIT(23,6) = 24: GOTO 5000 +7800 IF LOC <> 30 OR (INPTK(2) - ITEMOFF <> 3) THEN D$ = "8GWC KIV'B LW BPIB9": GOSUB 10000: GOTO 5000 +7830 IF INPTK(3) - ITEMOFF <> (IMOFF + 7) THEN D$= "2AQW ECP'V RWV KV VJGTG9": GOSUB 11000: GOTO 5000 +7840 IF ILOC(3) <> 0 THEN D$ = "2AQW FQP'V JCXG KV!1": GOSUB 11000: GOTO 5000 +7850 D$= "5DTZ UZY YMJ KZXJ NS YMJ GTC3": GOSUB 11000: ILOC(3) = -999: IC = IC - 1: REXIT(12,5) = 25: GOTO 5000 +8000 IF SAFED <> 0 THEN RETURN +8020 SAFED = INT(RND(3) * 3) + 1: RETURN +8025 IF SAFED <> 0 THEN RETURN +8030 SAFED = (INPTK(2) - DIROFF) + 1: IF SAFED > 3 THEN SAFED = 1 +8049 RETURN +8050 N1$ = VOCAB$(DIROFF+1): N2$ = VOCAB$(DIROFF+3): IF SAFED = 1 THEN N1$ = VOCAB$(DIROFF+2) +8070 IF SAFED = 3 THEN N2$ = VOCAB$(DIROFF+2) +8080 D$ = "3HASHULPHQWV RQ 9": GOSUB 10000: NTMSG$ = D2$ + N1$ +8085 D$ = "8 IVL 1": GOSUB 10000: NTMSG$ = NTMSG$ + D2$ + N2$ +8090 D$="3 GRRUV SURFHHGLQJ ZHOO; ILOH IRU SDWHQW4": GOSUB 10000: NTMSG$=NTMSG$+D2$ +8099 PRINT NTMSG$: RETURN +8200 IF LOC = 20 AND (INPTK(2) - ITEMOFF) = IMOFF + 4 THEN D$= "5UQJFXJ XUJHNKD QJKY, HJSYJW, TW WNLMY4": GOSUB 11000: GOTO 5000 +8299 D$ = "5MZM?9": GOSUB 11000: GOTO 5000 +9500 SCORE = 50 +9510 FOR I = 16 TO 20: IF ILOC(I) = 0 THEN SCORE = SCORE + 10 +9515 NEXT +9520 FOR I = 3 TO 30: FOR J = 1 TO 6: IF REXIT(I,J) = -1 THEN SCORE = SCORE -5 +9525 NEXT J, I +9530 FOR I = 1 TO 15: IF ILOC(I) = -1 THEN SCORE = SCORE - 5 +9535 NEXT +9540 PRINT "YOUR SCORE IS "; SCORE; " OUT OF A POSSIBLE 100": RETURN +10000 D2$ = "" : IF D$ = "" THEN GOTO 10070 +10005 CS = 0: OFF = ASC(MID$(D$,1,1))-48 +10010 FOR DC = 2 to LEN(D$)-1 +10020 D2AS = ASC(MID$(D$,DC,1)): IF D2AS >= 65 AND D2AS <= 90 THEN D2AS=D2AS - OFF: IF D2AS < 65 THEN D2AS = D2AS+26 +10030 D2$ = D2$ + CHR$(D2AS) +10040 IF D2AS >= 65 AND D2AS <= 90 THEN CS = CS + D2AS: IF CS > 9 THEN CS = CS-((INT(CS/10)) * 10) +10050 NEXT +10060 IF D$ <> "" THEN IF ASC(MID$(D$, LEN(D$), 1))-48 <> CS THEN PRINT "BAD CHECKSUM FOR "; D$; ", FOUND "; CS: GOTO 19999 +10070 IF SP THEN PRINT "."; +10099 RETURN +11000 GOSUB 10000: PRINT D2$: RETURN +15000 D$ = "6ZGEY NUAYK GJBKTZAXK5": GOSUB 11000 +15010 D$ = "2 HKPF VTGCUWTGU CPF XCNWCDNGU KP AQWT OCF WPENG VCAU' JQWUG3": GOSUB 11000 +15020 D$ = "4XCTI WMQTPI GSQQERHW: RSVXL, WSYXL, IXG. XS QSZI (SV NYWX 'R', 'W').4": GOSUB 11000 +15030 D$ = "4 XEOI ERH HVST, MRZIRXSVC, PSSO, VIEH, QSZI, ERH WS SR.5": GOSUB 11000 +15040 D$ = "7ZVTL JVTTHUKZ HYL JVTWSLE: 'TVCL AOL OBIJHW DPAO AOL ZWHUULY'1": GOSUB 11000: RETURN +19000 D$= "6EUA NGBK JOKJ3": GOSUB 11000: GOTO 19999 +19900 GOSUB 9500: IF SCORE = 100 THEN D$ = "2AQW JCXG YQP VJG ICOG!6": GOSUB 11000 +19999 END diff --git a/samples/sample.basic.txt b/samples/sample.basic.txt new file mode 100644 index 0000000..78b1db2 --- /dev/null +++ b/samples/sample.basic.txt @@ -0,0 +1,291 @@ +5 PR#3 : TEXT : HOME +10 PRINT "(1) GOSUB/RETURN/POP" +15 PRINT "(2) Basic I/O, IF/THEN" +20 PRINT "(3) Fibbonacci Sequence" +25 PRINT "(4) Guess my number" +30 PRINT "(5) Guess your number" +35 PRINT "(6) Approximate Pi" +40 PRINT "(7) Function tests" +45 PRINT "(8) Error tests" +50 PRINT "(9) Cellular automata" +55 PRINT "(10) Madlibs" +60 PRINT "(11) Lissajous Figures" +65 PRINT "(12) Screen Test" +70 PRINT "(13) DOS Sequential Access" +75 PRINT "(14) Lores Drawing with Joystick" +80 PRINT "(15) Lores Colors" +85 PRINT "(16) Mandelbrot Set" +85 PRINT "(17) Light Cycles" +90 PRINT "(18) Hires Demo" +92 PRINT "(19) DOS WRITE/APPEND" +94 PRINT "(20) ONERR ... RESUME" +94 PRINT "(21) CHR$ Tests" +95 PRINT: INPUT "Enter option: "; A : PRINT : HOME : ON A GOTO 100,200,300,400,500,600,700,800,1900,1000,1100,1200,2000,2100,2200,2300,2400,2500,2600,2700,2800 +98 HOME +99 END + +100 REM Gosub/Pop/Return tests +110 TRACE : PRINT "GOSUB 150" : GOSUB 150 +120 PRINT "GOSUB 160" : GOSUB 160 +130 PRINT : PRINT "Press any key: " : GET A$ : GOTO 5 +150 PRINT "RETURN" : NOTRACE : RETURN +160 PRINT "GOSUB 190" : GOSUB 190 +180 PRINT "RETURN - Shouldn't happen!" +190 PRINT "POP" : POP : PRINT "RETURN" : RETURN + +200 REM Basic input/output, expression, IF/THEN tests +205 PRINT "at line 200" +210 INPUT "Pick a number: "; A +215 PRINT A +220 IF (A) THEN PRINT "TRUE" +230 IF (NOT A) THEN PRINT "FALSE" +240 PRINT : PRINT "Press any key: " : GET A$ : GOTO 5 + +300 REM Fibbonacci +310 LA = 0 : CU = 1 +320 NX = LA + CU : PRINT NX +330 LA = CU : CU = NX +340 GOTO 320 + +400 REM Guess my number +405 PRINT "I'm picking a number between 1 and 100..." +410 N = INT( RND(1) * 100 ) + 1 +420 INPUT "Your guess? "; G +430 IF G = N THEN PRINT "Got it!" : PRINT : PRINT "Press any key: " : GET A$ : GOTO 5 +430 IF G < N THEN PRINT "Too low" : GOTO 420 +440 IF G > N THEN PRINT "Too high" : GOTO 420 + +500 REM Guess your number +510 INPUT "Pick a number between 1 and 100, then press Enter: "; X +520 MN = 1 : MX = 100: G = INT( RND(1) * 100 ) + 1 +530 PRINT "I guess ";G;" - enter 1 for too high, -1 for too low, 0 for got it" +540 INPUT R +550 IF R = 0 THEN PRINT "I guessed right!" : PRINT : PRINT "Press any key: " : GET A$ : GOTO 5 +540 IF R < 0 THEN MN = G + 1 : GOTO 560 +550 IF R > 0 THEN MX = G - 1 : GOTO 560 +560 IF MX = MN THEN PRINT "It must be "; MX; " - I guess you win." : END +570 G = INT( ( MX + MN ) / 2 ) : GOTO 530 + +600 REM Compute pi +610 I = 0 +620 SUM = 0 +630 SIGN = 1 +640 D = ( SIGN * ( 1 / ( 2 * I + 1 ) ) ) +645 SUM = SUM + D +650 SIGN = -SIGN +660 PI = 4 * SUM +670 PRINT "I = ";I;" PI = ";PI;" D = ";D +680 I = I + 1 +690 GOTO 640 + +700 REM Function tests +702 PRINT "ABS(-3.14) = "; ABS(-3.14) +704 PRINT "ASC('A') = "; ASC("A") +706 PRINT "ATN(1) = "; ATN(1) +708 PRINT "CHR$(65) = "; CHR$(65) +710 PRINT "COS(1) = "; COS(1) +712 PRINT "EXP(1) = "; EXP(1) +714 PRINT "INT(3.14) = "; INT(3.14) +716 PRINT "LEFT$('abcdef',3) = "; LEFT$("abcdef",3) +718 PRINT "LEN('abcdef') = "; LEN("abcdef") +720 PRINT "LOG(3.14) = "; LOG(3.14) +722 PRINT "MID$('abcdef',3) = "; MID$("abcdef",3) +724 PRINT "MID$('abcdef',3,2) = "; MID$("abcdef",3,2) +726 PRINT "RIGHT$('abcdef',3) = "; RIGHT$("abcdef",3) +728 PRINT "RND(1) = "; RND(1) +730 PRINT "SGN(-3.14) = "; SGN(-3.14) +732 PRINT "SIN(1) = "; SIN(1) +734 PRINT "SQR(9) = "; SQR(9) +736 PRINT "STR$(3.14) = "; STR$(3.14) +738 PRINT "TAN(1) = "; TAN(1) +740 PRINT "VAL('3.14') = "; VAL("3.14") +790 PRINT : PRINT "Press any key: " : GET A$ : GOTO 5 + +800 REM Error tests +810 A = 2 / 0 : PRINT "Shouldn't print this!" +820 PRINT : PRINT "Press any key: " : GET A$ : GOTO 5 + +900 REM Cellular automata +901 PRINT "Wolfram's CA rules" : PRINT "Try 110, 111, 118, 121, 126" : PRINT +902 INPUT "Rule: "; R : PRINT +904 DIM VT(8) : FOR I = 0 TO 7 : VT(I) = NOT( R / 2 = INT( R / 2 ) ) : R = INT(R / 2) : NEXT +910 S$ = " # " +912 PRINT ">";S$;"<" +914 N$ = " " +916 FOR I = 2 TO LEN(S$) - 1 +918 V = 4 * ( MID$( S$, I-1, 1) = "#" ) + 2 * ( MID$( S$, I, 1) = "#" ) + 1 * ( MID$( S$, I+1, 1) = "#" ) +920 IF VT(V) THEN N$ = N$ + "#" : GOTO 930 +922 N$ = N$ + " " +930 NEXT I +940 N$ = N$ + " " +950 S$ = N$ +960 GOTO 912 + +1000 REM Madlibs +1010 INPUT "Name: "; N$ +1020 INPUT "Verb: "; V$ +1030 INPUT "Noun: "; NN$ +1040 INPUT "Place: "; P$ +1050 S$ = "One day, " + N$ + " " + V$ + " to " + P$ + " to see the " + NN$ + "." +1060 PRINT S$ : PRINT +1070 PRINT : PRINT "Press any key: " : GET A$ : GOTO 5 + +1100 REM Lissajous Figures +1105 REM POKE 49168,0 : REM Clear keyboard strobe +1110 XA = 19 : YA = 19 +1120 XM = RND(1) * 0.5 + 0.5 : YM = RND(1) * 0.5 + 0.5 +1130 P = RND(1) * 3.14159 * 2 +1140 GR : COLOR= RND(1) * 14 + 1 +1150 FOR T = 0 TO 99 STEP 0.05 +1155 IF PEEK(49152) > 127 THEN POKE 49168,0 : GOTO 5 +1160 X = XA * COS( XM * T ) +1170 Y = YA * COS( YM * T + P ) +1180 PLOT 20 + X, 20 + Y +1190 NEXT T : GOTO 1100 + +1200 REM Screen Coordinates +1210 TEXT: HOME : FOR I = 1 TO 24 : HTAB 1 : VTAB I : PRINT I; : NEXT +1220 GR : FOR I = 0 TO 39 : COLOR= I : HLIN 0, 39 AT I : NEXT +1230 VTAB 24 : HTAB 10 : PRINT "Press Any Key To Continue"; : GET A$ +1240 HGR : C = 3 : FOR I = 0 TO 70 : HCOLOR= C : HPLOT I*2,I TO 279-I*2,I TO 279-I*2,159-I TO I*2,159-I TO I*2,I : C = C + 1 : IF C > 7 THEN C = 0 +1245 NEXT +1250 VTAB 24 : HTAB 10 : PRINT "Press Any Key To Continue"; : GET A$ +1290 GOTO 5 + +1900 REM Cellular automata +1901 HOME +1902 PRINT "Wolfram's CA rules" : PRINT "Try 110, 111, 118, 121, 126" : PRINT +1903 INPUT "Rule: "; R : PRINT +1904 DIM VT(8) : FOR I = 0 TO 7 : VT(I) = NOT( R / 2 = INT( R / 2 ) ) : R = INT(R / 2) : NEXT +1910 DIM C(30) : DIM N(30) : N(15) = 1 +1912 FOR I = 0 TO 30 : C(I) = N(I) : PRINT C(I); : NEXT : PRINT +1916 FOR I = 2 TO 30 - 1 +1918 V = 4 * C(I-1) + 2 * C(I) + 1 * C(I+1) +1920 N(I) = VT(V) +1930 NEXT I +1940 GOTO 1912 + +2000 REM DOS Sequential Text File +2005 PRINT "First, knowing it has 4 lines..." : PRINT +2010 PRINT CHR$(4)"OPEN JABBERWOCKY" +2015 PRINT CHR$(4)"READ JABBERWOCKY" +2020 FOR I = 1 TO 4 : INPUT A$ : PRINT A$ : NEXT +2025 PRINT CHR$(4)"CLOSE" +2030 PRINT : PRINT "Now with ONERR..." : PRINT +2035 PRINT CHR$(4)"OPEN JABBERWOCKY" +2040 PRINT CHR$(4)"READ JABBERWOCKY" +2045 ONERR GOTO 2055 +2050 INPUT A$ : PRINT A$ : GOTO 2050 +2055 PRINT : PRINT "Hit EOF " : POKE 216,0 : PRINT CHR$(4)"CLOSE" +2090 PRINT : PRINT "Press any key to continue: " : GET A$ : GOTO 5 + +2100 REM Lores Drawing +2110 GR +2115 OX = -1 : OY = -1 +2116 C = 0 +2120 X = INT( PDL(0) / 256 * 40 ) +2130 Y = INT( PDL(1) / 256 * 48 ) +2135 HTAB 1 : VTAB 23 : PRINT X ; " " ; Y ; " " +2140 REM IF ( OX <> X OR OY <> Y ) AND OX <> -1 AND OY <> -1 THEN COLOR= 0 : PLOT OX, OY +2150 COLOR= C : PLOT X, Y +2160 OX = X : OY = Y : C = C + 1 : IF C > 15 THEN C = 0 +2170 GOTO 2120 + +2200 REM Color Chart +2210 GR +2220 DATA 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, 10, 11, -1, -1, 12, 13, -1, -1, 14, 15, -2 +2230 MX = 0 : MY = 0 : XS = 6 : YS = 9 +2240 READ C : IF C = -2 THEN HTAB 1 : VTAB 22 : PRINT "Press any key: " : GET A$ : GOTO 5 +2250 IF C = -1 THEN GOTO 2270 +2260 COLOR= C : FOR Y = 0 TO YS-1 : HLIN MX*XS,MX*XS+(XS-2) AT MY*(YS+1)+Y : NEXT +2270 MY = MY + 1 : IF MY > 3 THEN MY = 0 : MX = MX + 1 +2280 GOTO 2240 + +2300 REM Mandelbrot Set +2310 HOME : GR : POKE 49234,0 +2320 FOR X = 0 TO 39 : FOR Y = 1 TO 24 +2330 I = X / 40 * 3 - 2 : J = Y / 48 * 2 - 1 +2340 GOSUB 2360 : COLOR= C : PLOT X, Y : PLOT X,48 - Y +2350 NEXT Y : NEXT X : HTAB 1 : VTAB 22 : PRINT "Press any key: " : GET A$ : GOTO 5 +2360 IT = 0 : S = I : T = J +2370 S1 = S*S - T*T + I : T = 2*S*T + J: S = S1 : IT = IT + 1 +2380 IF ((S*S + T*T) < 4) AND IT < 16 THEN GOTO 2370 +2390 C = IT : RETURN + +2400 REM Light Cycles Game +2410 HOME : GR : REM TODO: Fullscreen +2420 X = 19 : Y = 38 : DX = 0 : DY = -1 +2430 COLOR= 15 : HLIN 0,39 AT 0: HLIN 0,39 AT 39: VLIN 0,39 AT 0 : VLIN 0,39 AT 39 +2440 HTAB 1 : VTAB 22 : PRINT "Press any key to start: " : GET A$ : HOME +2450 COLOR= 2: PLOT X,Y +2460 K = PEEK(49152) : POKE 49168,0 +2461 LX = DX : LY = DY +2462 IF K = 8+128 THEN DX = -1 : DY = 0 +2463 IF K = 21+128 THEN DX = 1 : DY = 0 +2464 IF K = 11+128 THEN DX = 0 : DY = -1 +2465 IF K = 10+128 THEN DX = 0 : DY = 1 +2466 IF ( LX AND LX = -DX ) OR (LY AND LY = -DY) THEN DX = LX : DY = LY +2470 X = X + DX : Y = Y + DY +2480 IF SCRN(X,Y) <> 0 THEN HTAB 1 : VTAB 23 : PRINT "Crashed! Press any key to continue: " : GET A$ : GOTO 5 +2490 HTAB 1 : VTAB 21 : SC = SC + 10 : PRINT "Score: "; SC +2490 GOTO 2450 + +2500 REM Hires Demo +2510 HOME : HGR +2520 W = 279 : H = 159 +2530 FOR I = 0 TO 1 STEP 0.05 +2535 HCOLOR= 1 +2540 HPLOT 0,H * I TO W* (1-I),0 +2545 HCOLOR= 2 +2550 HPLOT 0,H * (1-I) TO W* (1-I),H +2555 HCOLOR= 5 +2560 HPLOT W,H * I TO W * I,0 +2565 HCOLOR= 6 +2570 HPLOT W,H * (1-I) TO W * I,H +2575 NEXT +2580 HTAB 1 : VTAB 22 : PRINT "Press any key to continue: " : GET A$ : GOTO 5 + +2600 REM DOS WRITE/APPEND +2610 PRINT CHR$(4)"OPEN FOO" +2615 PRINT CHR$(4)"WRITE FOO" +2620 FOR I = 1 TO 5 : PRINT "WRITE - "; CHR$(ASC("A") - 1 + I ) : NEXT +2625 PRINT CHR$(4)"CLOSE FOO" +2630 PRINT CHR$(4)"APPEND FOO" +2635 PRINT CHR$(4)"WRITE FOO" +2640 FOR I = 6 TO 10 : PRINT "APPEND - ";CHR$(ASC("A") - 1 + I ) : NEXT +2645 PRINT CHR$(4)"CLOSE FOO" +2650 PRINT CHR$(4)"OPEN FOO" +2655 PRINT CHR$(4)"READ FOO" +2660 FOR I = 1 TO 10 : INPUT A$ : PRINT "READ LINE ";I;": ";A$ : NEXT +2665 PRINT CHR$(4)"CLOSE FOO" +2670 PRINT : PRINT "Press any key to continue: " : GET A$ : GOTO 5 + +2700 REM ONERR ... RESUME +2710 PRINT "First, RESUME into an IF statement" +2712 ONERR GOTO 2718 +2714 PRINT "Testing... " : X = 0 : IF 1 / X THEN PRINT "Succeeded!" +2716 PRINT "That worked!" : GOTO 2750 +2718 PRINT "Oops! How about this... " : X = 1 : RESUME +2750 ONERR GOTO 2785 +2755 PRINT "Trigger division by zero with X / Y" +2760 INPUT "X = ";X +2765 INPUT "Y = ";Y +2770 PRINT "X / Y = ";X;" / ";Y;" = ";(X/Y) +2775 POKE 216,0 : REM Clear ONERR Flag +2780 PRINT "That worked! Press any key to continue: " : GET A$ : GOTO 5 +2785 PRINT : PRINT "Oops, caught an error. Try again": INPUT "Y = ";Y : RESUME + +2800 REM CONTROL KEY TESTS +2810 PR#0 : TEXT : HOME +2820 HTAB 20 : VTAB 24 : PRINT "1"CHR$(10)"2"; +2830 HTAB 1 : VTAB 11 : PRINT CHR$(8)"3"; +2840 HTAB 1 : VTAB 1 : PRINT CHR$(8)"4"; +2851 HTAB 16 : VTAB 23 : PRINT "1-->"; +2852 HTAB 17 : VTAB 24 : PRINT "2-->"; +2853 HTAB 36 : VTAB 10 : PRINT "3-->"; +2854 HTAB 36 : VTAB 1 : PRINT "4-->"; +2860 VTAB 10 : HTAB 1 : PRINT "Press key to beep:"; : GET A$ : PRINT CHR$(7) +2870 VTAB 11 : HTAB 1 : PRINT "Press any key:"; : GET A$ : GOTO 5 + + + diff --git a/samples/sample.bitmaps.txt b/samples/sample.bitmaps.txt new file mode 100644 index 0000000..4e4ee25 --- /dev/null +++ b/samples/sample.bitmaps.txt @@ -0,0 +1,408 @@ +0 REM ** Apple ][ in Hi-Res graphics (280x192) ** +5 HGR2 : HCOLOR= 1 +10 FOR Y = 0 TO 191 +20 FOR X = 0 TO 279 STEP 16 +30 READ N +40 FOR I = 0 TO 15 +50 N = N/2 : IF N <> INT(N) THEN HPLOT X+I, Y : N = INT(N) +60 NEXT +70 NEXT +80 NEXT +90 GET NxtPct$ + +100 REM ** Apple skull in Hi-Res graphics (280x192) ** +105 HGR2 : HCOLOR= 3 +110 FOR Y = 0 TO 191 +120 FOR X = 0 TO 279 STEP 16 +130 READ N +140 FOR I = 0 TO 15 +150 N = N/2 : IF N <> INT(N) THEN HPLOT X+I, Y : N = INT(N) +160 NEXT +170 NEXT +180 NEXT + +1000 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1020 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1030 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1040 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1050 DATA 0,0,0,0,44352,21832,23253,46811,56173,27354,18773,9362,43650,4,0,0,0,0 +1060 DATA 0,0,0,0,21072,43669,42282,18724,9362,38181,22186,54613,21852,9,0,0,0,0 +1070 DATA 0,0,0,0,43688,21684,21845,21845,21845,42325,37460,19114,35113,42,0,0,0,0 +1080 DATA 0,0,0,0,21832,43877,43690,43690,43690,23210,46411,10532,43603,20,0,0,0,0 +1090 DATA 0,0,0,0,55892,54682,30582,32735,57343,28125,27579,46811,46550,18,0,0,0,0 +1100 DATA 0,0,0,0,9636,11434,19017,16400,36864,42130,38052,19114,9513,181,0,0,0,0 +1110 DATA 0,0,0,0,27290,51538,54442,55014,26331,39594,21834,43301,19602,73,0,0,0,0 +1120 DATA 0,0,0,0,39524,13142,43861,11606,44469,25941,43701,21850,43349,42,0,0,0,0 +1130 DATA 0,0,0,0,25930,19626,21845,21161,18506,43690,21834,10953,21161,82,0,0,0,0 +1140 DATA 0,0,0,0,19126,46418,43690,43690,56149,39594,43316,42282,22102,213,0,0,0,0 +1150 DATA 0,0,0,0,46409,19094,21845,21845,38569,25940,38571,23126,42153,138,0,0,0,0 +1160 DATA 0,0,0,0,19114,21866,43669,43690,26966,10923,21157,18857,10917,309,0,0,0,0 +1170 DATA 0,0,0,0,13653,43669,21866,21845,19113,54613,44396,38482,21850,105,0,0,0,0 +1180 DATA 0,0,0,0,10921,21845,21845,21845,21845,21845,21845,21845,19029,74,0,0,0,0 +1190 DATA 0,0,0,0,21835,43689,43690,43690,43690,43690,43690,43690,46506,690,0,0,0,0 +1200 DATA 0,0,0,32768,10932,43691,21845,21845,21845,21845,21845,21845,21074,341,0,0,0,0 +1210 DATA 0,0,0,32768,43690,21846,43690,43690,43690,43690,43690,19114,19629,586,0,0,0,0 +1220 DATA 0,0,0,0,21835,43689,22229,56155,28086,23387,21845,46421,46418,181,0,0,0,0 +1230 DATA 0,0,0,16384,43701,23210,26925,21845,21845,42341,43690,19114,37525,420,0,0,0,0 +1240 DATA 0,0,0,16384,38218,42326,38610,43690,43690,23210,21845,21845,44395,842,0,0,0,0 +1250 DATA 0,0,0,32768,23221,23209,27309,23253,21845,43693,43690,43690,21140,557,0,0,0,0 +1260 DATA 0,0,0,16384,42313,54614,21866,42283,43690,21842,23387,21845,21867,745,0,0,0,0 +1270 DATA 0,0,0,40960,22198,9909,43669,28084,55003,46774,42324,43690,43668,1682,0,0,0,0 +1280 DATA 0,0,0,16384,39253,27978,28011,21867,13653,51629,23210,21845,21867,2349,0,0,0,0 +1290 DATA 0,0,0,40960,54954,43738,21338,43669,43690,44361,54613,43690,43690,1386,0,0,0,0 +1300 DATA 0,0,0,40960,19146,21141,39589,28010,21845,23227,10934,21869,21845,2709,0,0,0,0 +1310 DATA 0,0,0,24576,21813,28011,46427,51885,44470,54098,54698,56146,21162,1365,0,0,0,0 +1320 DATA 0,0,0,36864,43882,39770,26026,23381,27305,46765,44373,9389,44373,2730,0,0,0,0 +1330 DATA 0,0,0,24576,21845,45733,44629,46442,21846,9563,10925,56149,21162,5461,0,0,0,0 +1340 DATA 0,0,0,20480,27307,27995,22890,51867,44470,56018,54634,43690,44374,682,0,0,0,0 +1350 DATA 0,0,0,45056,43860,19306,42715,44470,27476,46765,23370,21869,21161,3413,0,0,0,0 +1360 DATA 0,0,0,18432,21867,55957,46762,46441,21677,42331,43701,43858,44470,6826,0,0,0,0 +1370 DATA 0,0,0,45056,43862,43738,22870,27285,56171,28082,54637,23222,25941,9557,0,0,0,0 +1380 DATA 0,0,0,43008,54452,21942,44469,39798,38612,21846,44458,54605,43690,2730,0,0,0,0 +1390 DATA 0,0,0,21504,21931,27941,54955,54698,30006,43693,11093,43737,19798,13653,0,0,0,0 +1400 DATA 0,0,0,43008,43866,43738,46426,27309,43883,56793,29294,22187,55989,19114,0,0,0,0 +1410 DATA 0,0,0,26624,46245,21933,10965,44373,23244,21803,52649,46422,9546,5461,0,0,0,0 +1420 DATA 0,0,0,37888,21942,47957,60845,55002,54965,44470,23405,43737,28085,10923,0,0,0,0 +1430 DATA 0,0,0,27648,43865,54490,22122,22955,13659,27349,43611,22182,53933,13658,0,0,0,0 +1440 DATA 0,0,0,54272,27302,11691,43739,46774,27498,21867,46546,46429,19818,19154,0,0,0,0 +1450 DATA 0,0,0,10752,22877,27445,28053,43861,54997,61110,22190,43881,55957,46390,0,0,0,0 +1460 DATA 0,0,0,54272,43882,56022,55990,23258,44379,21930,27317,23255,38253,10965,0,0,0,0 +1470 DATA 0,0,0,46592,56021,21866,43885,46509,23222,44397,44397,42650,11690,21801,0,0,0,0 +1480 DATA 0,0,0,18944,21654,44461,21929,27499,46549,56021,54986,28010,59995,46518,0,0,0,0 +1490 DATA 0,0,0,46336,43885,56149,27990,54869,27434,43867,23389,23253,38357,19114,1,0,0,0 +1500 DATA 0,0,0,27136,56537,43706,55997,23278,44407,14006,46443,42331,46762,46421,0,0,0,0 +1510 DATA 0,0,0,38144,21846,46443,46546,43866,54698,54634,43738,56746,10605,27309,0,0,0,0 +1520 DATA 0,0,0,56064,44470,22230,43863,30421,46813,28077,22357,43885,28058,38323,1,0,0,0 +1530 DATA 0,0,0,27136,29865,28077,22189,43691,44373,56022,47790,23125,23381,44365,0,0,0,0 +1540 DATA 0,0,0,38272,54999,46426,47834,55158,56170,43866,54645,46554,21101,45786,2,0,0,0 +1550 DATA 0,0,0,23168,44378,54966,54709,27866,46519,46773,43946,42669,28074,19251,1,0,0,0 +1560 DATA 0,0,0,29952,27317,43877,27478,44459,43866,23254,23895,23899,22235,46765,2,0,0,0 +1570 DATA 0,0,0,52608,54630,23982,44731,56173,30390,27501,27501,27061,44373,54634,0,0,0,0 +1580 DATA 0,0,0,43584,44717,46426,23253,46421,44469,44461,54965,56234,27318,44373,5,0,0,0 +1590 DATA 0,0,0,23360,23221,54709,46442,44475,56022,46426,23254,38487,56173,37558,2,0,0,0 +1600 DATA 0,0,0,46464,46422,23403,27575,54998,43866,55029,43866,47866,38226,28074,5,0,0,0 +1610 DATA 0,0,0,27328,27499,46765,27994,56173,28013,28075,60779,27466,27309,44373,1,0,0,0 +1620 DATA 0,0,0,19744,23341,27355,54965,43701,46518,44374,21933,54967,28086,21211,6,0,0,0 +1630 DATA 0,0,0,47808,54453,44466,39787,23894,56149,23226,46773,38100,39786,56116,10,0,0,0 +1640 DATA 0,0,0,54976,46938,46766,31446,60379,46811,46573,60891,31661,46413,44389,5,0,0,0 +1650 DATA 0,0,0,21920,28075,28013,26029,13915,44397,28309,39597,42678,27317,21165,5,0,0,0 +1660 DATA 0,0,0,43616,43702,56021,44918,28086,22235,43899,56181,56666,52662,44506,6,0,0,0 +1670 DATA 0,0,0,31648,56749,43950,55981,55021,60854,46806,46507,27373,23405,46677,13,0,0,0 +1680 DATA 0,0,0,54608,46490,23925,46811,56154,56170,28074,27486,54699,27306,21931,9,0,0,0 +1690 DATA 0,0,0,44768,22235,63195,28086,28087,46815,56189,22389,44893,46813,28090,23,0,0,0 +1700 DATA 0,0,0,46512,60854,44470,56173,46829,28085,46807,47787,46443,28085,56171,10,0,0,0 +1710 DATA 0,0,0,56144,23382,56173,28086,56155,46810,23405,28125,56045,56150,21850,45,0,0,0 +1720 DATA 0,0,0,56168,46765,46811,56173,28086,56175,60854,46966,46939,22253,46771,21,0,0,0 +1730 DATA 0,0,0,46768,28122,46811,46813,46829,28085,46811,56027,28086,27995,44507,42,0,0,0 +1740 DATA 0,0,0,46800,46797,56173,28086,64347,63342,56182,28086,56173,46518,21846,23,0,0,0 +1750 DATA 0,0,0,27352,46811,56173,56173,19894,44763,28397,46811,46811,56245,47786,13,0,0,0 +1760 DATA 0,0,0,56752,28118,46811,30445,48879,56045,56758,56246,28086,54891,28149,90,0,0,0 +1770 DATA 0,0,0,43864,46765,56173,61142,62298,48566,56157,28013,56027,15214,54939,21,0,0,0 +1780 DATA 0,0,0,30440,46811,46957,44477,13,512,8258,46808,46957,46554,38325,54,0,0,0 +1790 DATA 0,0,0,28084,56171,28086,56171,21835,8277,1313,56801,28086,27483,31595,77,0,0,0 +1800 DATA 0,0,0,56152,46806,56173,48566,25126,19106,21012,27554,56027,46957,43734,21,0,0,0 +1810 DATA 0,0,0,23400,56173,60854,30429,9383,18696,34978,56692,44470,55990,28085,59,0,0,0 +1820 DATA 0,0,0,60852,28086,46811,60342,43798,37013,45644,47969,56173,44506,22198,85,0,0,0 +1830 DATA 0,0,0,56172,56173,28525,44763,56653,59324,45896,27556,30427,30391,60779,54,0,0,0 +1840 DATA 0,0,0,46808,46950,56054,56173,10,44838,41835,56676,44470,56173,39638,45,0,0,0 +1850 DATA 0,0,0,28084,56047,28077,32187,21159,10402,43306,46824,56173,22234,46509,170,0,0,0 +1860 DATA 0,0,0,56170,28074,47067,43885,9293,42157,39273,56161,30427,60855,27498,91,0,0,0 +1870 DATA 0,0,0,46812,46957,31421,30647,19083,42922,46028,46949,44470,56173,56685,54,0,0,0 +1880 DATA 0,0,0,28084,28087,55147,60790,56102,12420,0,28388,30427,14043,22231,213,0,0,0 +1890 DATA 0,0,0,56170,56170,28406,57051,9253,17449,21803,62882,56182,28086,46509,45,0,0,0 +1900 DATA 0,0,0,46812,30445,48559,46573,18759,35154,18576,23410,46811,56173,27498,91,0,0,0 +1910 DATA 0,0,0,28010,60855,29402,23479,18733,4738,8482,28361,28087,46811,22199,181,0,0,0 +1920 DATA 0,0,0,56246,54998,61373,61278,46814,60093,39766,60852,56246,28086,48493,109,0,0,0 +1930 DATA 0,0,0,56172,48566,23915,47851,65531,65535,65279,56191,56174,28086,26059,171,0,0,0 +1940 DATA 0,0,0,28013,46811,46838,28093,43691,21842,27573,56299,28085,46811,56173,342,0,0,0 +1950 DATA 0,0,0,56246,27574,56239,63451,56798,61165,46806,46765,56174,28086,23387,109,0,0,0 +1960 DATA 0,0,0,46810,57205,30429,44651,30573,48063,57211,61150,46813,56173,46806,365,0,0,0 +1970 DATA 0,0,0,56173,46443,28538,56799,56251,46810,47853,23413,28123,46811,28013,91,0,0,0 +1980 DATA 0,0,0,46957,31670,56039,48058,61174,28525,30175,60911,56758,28086,46811,426,0,0,0 +1990 DATA 0,0,0,56027,55158,48605,60277,47981,64247,61274,48054,56173,56173,54998,349,0,0,0 +2000 DATA 0,0,32768,28084,28395,63419,57071,56799,44510,55031,46941,46811,46813,28077,171,0,0,0 +2010 DATA 0,0,32768,46955,27989,43607,14038,56245,57050,47982,30445,56247,28086,23387,437,0,0,0 +2020 DATA 0,0,0,55991,56254,57326,60858,46774,30139,46957,44470,28022,56171,60118,854,0,0,0 +2030 DATA 0,0,32768,28122,47987,30141,64439,28123,56247,61147,56173,46829,46813,22381,219,0,0,0 +2040 DATA 0,0,32768,46957,30423,46771,38765,57213,28534,23995,28091,56795,28086,47835,950,0,0,0 +2050 DATA 0,0,32768,56173,55150,56302,32507,62903,46829,48109,48887,48045,46811,28077,685,0,0,0 +2060 DATA 0,0,32768,28086,48565,28511,62935,44790,65243,60254,60270,28030,56173,60246,346,0,0,0 +2070 DATA 0,0,32768,47981,27387,48569,43886,31597,54719,57083,56794,46805,46811,22253,747,0,0,0 +2080 DATA 0,0,32768,30427,63319,60151,57277,47071,44917,28077,48055,56251,28086,46811,941,0,0,0 +2090 DATA 0,0,49152,44470,24045,47067,48491,61114,30446,64375,46781,28526,56175,27990,347,0,0,0 +2100 DATA 0,0,16384,56173,48058,57006,62430,56181,64365,22510,60907,47853,46837,46829,694,0,0,0 +2110 DATA 0,0,49152,32182,63319,31613,44923,48623,45019,48477,24543,62939,28078,55003,1002,0,0,0 +2120 DATA 0,0,16384,42315,19050,54739,30421,30557,55991,64443,47802,44983,30573,47963,1325,0,0,0 +2130 DATA 0,0,49152,52076,46810,43670,43350,19122,13658,17765,25957,10794,19669,21157,1749,0,0,0 +2140 DATA 0,0,16384,32187,31671,56827,57274,46807,46829,57005,44462,54765,43690,44470,682,0,0,0 +2150 DATA 0,0,16384,56247,55150,30685,30447,65405,61367,64507,65398,65243,63455,56157,1373,0,0,0 +2160 DATA 0,0,16384,56173,61149,61038,46813,54747,46814,43886,10973,21943,23925,46827,1718,0,0,0 +2170 DATA 0,0,49152,28086,48635,56765,61302,48055,32237,56759,63419,28542,47835,46813,213,0,0,0 +2180 DATA 0,0,32768,46811,27541,48107,23995,61309,55005,32733,56183,47845,55223,28086,987,0,0,0 +2190 DATA 0,0,40960,32237,63343,28087,64503,46806,48059,54651,28374,28123,28013,56171,2870,0,0,0 +2200 DATA 0,0,49152,60342,44798,63198,46766,32239,28535,48055,48573,47039,46811,46813,365,0,0,0 +2210 DATA 0,0,40960,55133,56786,28653,28539,56251,63214,61166,27611,55989,31670,27355,3029,0,0,0 +2220 DATA 0,0,49152,48886,30143,55995,65015,63350,56797,24029,56763,32214,55151,56758,686,0,0,0 +2230 DATA 0,0,40960,27051,56149,13636,18701,44763,46811,48053,47981,55163,56058,46518,2909,0,0,0 +2240 DATA 0,0,40960,46973,48891,0,4224,0,512,8200,33344,2052,24576,43883,745,0,0,0 +2250 DATA 0,0,49152,57046,27566,18472,1232,3075,16432,256,5,32800,50180,56158,3510,0,0,0 +2260 DATA 0,0,53248,31598,30427,33810,16384,9362,34869,2338,10772,41312,51521,46773,813,0,0,0 +2270 DATA 0,0,24576,54715,24445,12296,720,258,20608,32896,16420,514,25984,56171,1782,0,0,0 +2280 DATA 0,0,40960,28533,28087,9282,8321,11265,16434,800,6665,4168,49162,46518,2765,0,0,0 +2290 DATA 0,0,53248,47982,32219,8,33808,2340,2320,2305,10244,41232,25600,22235,1453,0,0,0 +2300 DATA 0,0,24576,30427,27579,9248,1,16384,36940,8228,16673,2,49732,47798,2933,0,0,0 +2310 DATA 0,0,53248,28525,22391,130,8776,520,0,0,0,544,49152,27478,5467,0,0,0 +2320 DATA 0,0,40960,46523,32109,16384,0,4225,256,4672,1028,36864,49280,55021,1750,0,0,0 +2330 DATA 0,0,28672,61165,950,1168,1025,16400,9289,32777,8480,137,17444,44379,3501,0,0,0 +2340 DATA 0,0,24576,46807,33499,35104,10540,33060,4644,9252,32897,1026,53768,46518,5466,0,0,0 +2350 DATA 0,0,53248,56766,37358,4,16384,2112,0,2114,1040,10501,49217,56246,2805,0,0,0 +2360 DATA 0,0,26624,48053,29629,16672,2578,20516,34113,16392,16672,16402,17040,46699,1942,0,0,0 +2370 DATA 0,0,45056,27499,875,1216,18695,33064,4626,10512,129,7424,52520,27350,3259,0,0,0 +2380 DATA 0,0,24576,57055,439,145,9218,8288,516,8213,34120,38,32768,44509,6869,0,0,0 +2390 DATA 0,0,55296,46554,37854,37376,2064,36868,2368,33864,16512,8704,41097,46763,2998,0,0,0 +2400 DATA 0,0,45056,60853,362,0,33024,256,8194,4098,1040,2056,17408,56029,5485,0,0,0 +2410 DATA 0,0,26624,57199,2493,146,4130,528,0,128,1,129,32784,27499,11947,0,0,0 +2420 DATA 0,0,59392,23258,8663,17408,0,36864,4680,17425,8776,16384,34946,44461,2778,0,0,0 +2430 DATA 0,0,45056,60909,16826,2313,9252,585,2053,0,0,4680,49152,30390,5595,0,0,0 +2440 DATA 0,0,22528,47031,3959,130,37010,33856,37128,41320,5250,8210,33425,44509,11061,0,0,0 +2450 DATA 0,0,59392,56666,53230,4608,0,128,8723,16896,516,2200,29698,56171,3766,0,0,0 +2460 DATA 0,0,46080,47853,19117,9289,42057,8740,1029,136,37000,24576,57632,46774,13677,0,0,0 +2470 DATA 0,0,55296,30646,1915,772,26650,2240,18468,36944,8705,16530,45888,44397,3498,0,0,0 +2480 DATA 0,0,45056,55003,36310,4608,16400,32896,39170,33344,2305,1040,24577,56283,6877,0,0,0 +2490 DATA 0,0,46080,47837,1467,64,9280,530,20,8228,1572,18500,25634,46427,27498,0,0,0 +2500 DATA 0,0,29696,30651,10103,8194,9,1024,4609,264,8320,0,45184,27501,3415,0,0,0 +2510 DATA 0,0,55296,44758,1750,2312,0,16449,16416,4096,2,273,24592,44763,14061,0,0,0 +2520 DATA 0,0,46080,62829,1981,0,9280,0,1032,32896,0,18432,24578,46517,5546,0,0,0 +2530 DATA 0,0,46080,23517,42347,20553,137,18954,128,1041,32,128,41472,56171,23349,0,0,0 +2540 DATA 0,0,55296,28522,18167,34848,1280,10281,41425,6406,54452,1606,25684,46767,5494,0,0,0 +2550 DATA 0,0,55808,55991,1966,262,34850,256,1024,8194,32800,9216,45186,44404,14029,0,0,0 +2560 DATA 0,0,44032,46574,42717,20553,576,9252,16420,17681,8452,129,57616,21979,10971,0,0,0 +2570 DATA 0,0,29696,28597,891,18432,386,43013,192,1028,144,9764,17586,61111,11690,0,0,0 +2580 DATA 0,0,55808,55899,9958,8340,35104,4104,16976,7171,36864,1024,26624,23402,21869,0,0,0 +2590 DATA 0,0,44032,60918,17885,16450,1,4388,1090,18578,8490,8329,57602,56029,23254,0,0,0 +2600 DATA 0,0,29696,47019,950,1024,1028,16385,16672,256,128,1024,17444,27483,11099,0,0,0 +2610 DATA 0,0,55808,27998,1883,10384,8226,1024,0,0,4096,66,24641,55147,46762,0,0,0 +2620 DATA 0,0,43520,46837,62191,3,0,72,4105,8210,18,10368,41224,44253,5485,0,0,0 +2630 DATA 0,0,56320,30422,31605,37191,1152,4353,576,256,0,16,49152,48054,27350,0,0,0 +2640 DATA 0,0,55808,60846,54254,65510,21071,16932,42002,2084,19073,37506,30373,54635,39770,0,0,0 +2650 DATA 0,0,46336,23413,2715,65250,8199,34882,288,8769,8228,65520,57343,46806,14005,0,0,0 +2660 DATA 0,0,55808,28086,47995,43878,2342,4360,18564,17416,4368,23393,43354,44461,43366,0,0,0 +2670 DATA 0,0,27648,46811,64469,30693,16967,16913,9234,4242,33921,63204,46957,23226,23387,0,0,0 +2680 DATA 0,0,27904,56795,18798,56995,4101,33826,288,577,8266,23400,28087,46551,9901,0,0,0 +2690 DATA 0,0,46592,27501,56251,60770,9382,10569,37450,9224,4625,56161,56026,27498,46517,0,0,0 +2700 DATA 0,0,55808,46774,749,48100,37447,55972,21693,37458,33856,46820,46957,54877,27242,0,0,0 +2710 DATA 0,0,44288,56813,438,30432,3,0,2410,132,18570,28064,28087,46827,38605,0,0,0 +2720 DATA 0,0,29952,46411,37741,61360,18726,274,16384,9248,273,56178,56026,44502,13750,1,0,0 +2730 DATA 0,0,44544,27574,32475,22895,1031,18432,33280,8,4096,46944,22381,55981,26922,0,0,0 +2740 DATA 0,0,54528,57213,60854,47031,65533,65535,48639,56277,28086,27851,46251,21850,19893,1,0,0 +2750 DATA 0,0,47872,46250,43885,61148,64510,47103,65535,65535,65535,56255,27510,43883,23405,0,0,0 +2760 DATA 0,0,54784,27629,57051,56763,22229,27989,27477,46683,42325,46810,47085,46773,45642,0,0,0 +2770 DATA 0,0,44288,57142,46518,56181,49006,65467,57087,28142,56251,28085,27803,23259,9653,1,0,0 +2780 DATA 0,0,55936,55670,56246,28078,62907,43774,60909,48061,49015,56175,21942,54613,27990,0,0,0 +2790 DATA 0,0,46592,27565,28379,48091,56301,32213,46939,30427,46445,46810,61146,43958,55978,0,0,0 +2800 DATA 0,0,26880,57051,46518,63165,44894,47023,32511,61303,30446,28091,21867,23211,9653,1,0,0 +2810 DATA 0,0,44288,46442,56173,44502,30395,56189,60906,56046,56283,54997,44470,46422,11597,1,0,0 +2820 DATA 0,0,20992,27349,28379,56251,48630,61163,56247,47069,46902,56174,56022,43884,23402,0,0,0 +2830 DATA 0,0,21504,38189,46420,48469,60333,32222,48575,32443,30459,44475,46509,22197,37461,0,0,0 +2840 DATA 0,0,41984,27346,21163,41645,21802,43829,46954,54646,43725,23253,43829,43338,10922,0,0,0 +2850 DATA 0,0,10240,22165,43861,22378,56181,54954,18770,9637,44341,42282,19050,19029,42313,0,0,0 +2860 DATA 0,0,32768,43304,27988,27989,43723,44245,30429,47963,21354,23253,46501,21930,5270,0,0,0 +2870 DATA 0,0,0,0,0,43177,21658,27501,54965,54618,27989,43691,9370,43593,2404,0,0,0 +2880 DATA 0,0,0,0,0,0,0,33920,35138,10916,37525,9556,21797,37010,520,0,0,0 +2890 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +2900 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +2910 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +2920 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + +3000 DATA 37449,18724,9362,37449,18724,9362,37154,18724,9362,8777,9361,8738,8738,18722,9362,37449,18724,82 +3020 DATA 9362,37449,18724,9362,37449,18724,37444,37412,37412,4388,9353,8738,8738,9361,37449,18724,9362,73 +3030 DATA 18724,9362,37449,18724,9362,37449,9362,18761,9362,19017,37458,38036,38036,18724,9362,37449,18724,18 +3040 DATA 21065,18725,21842,21833,18725,9362,18724,37394,18724,37010,9348,8521,18761,37450,18724,9362,38229,42 +3050 DATA 9362,37450,18724,37418,37448,18724,37449,9380,37449,9508,18729,18978,37410,9360,37449,18724,42130,36 +3060 DATA 18724,9361,37449,9540,9365,4681,18725,37522,18724,21650,37458,38036,9364,18725,21650,37449,18724,73 +3070 DATA 43593,19108,9362,43177,18720,42130,37448,9252,37449,33060,9348,8481,18721,37448,9508,9362,4681,18 +3080 DATA 1170,36905,21796,17701,37462,2340,9361,18761,9362,43593,18728,19018,37450,9362,37449,18724,25938,85 +3090 DATA 21156,9874,35145,10824,18721,42130,37450,37412,18724,63634,33938,37000,9364,37450,9362,37449,34954,36 +3100 DATA 42025,18724,9362,18581,37450,18724,18576,9362,33937,61192,21066,19026,35106,9360,18724,9362,10833,73 +3110 DATA 2706,42057,18724,38178,9364,4681,9509,18761,21028,43474,34961,37156,8776,18725,37449,18724,41610,18 +3120 DATA 20772,4754,37449,9364,18721,42130,34884,4624,35145,62052,21028,9362,21541,8778,9362,37449,5204,36 +3130 DATA 8777,42057,9364,18721,37450,16932,21138,18762,21010,62618,33929,19012,33416,18576,18725,9362,41633,73 +3140 DATA 38034,2340,18721,37450,9364,10385,33833,41508,34980,64532,10578,4393,10533,4645,37448,18724,18698,18 +3150 DATA 8484,42129,9364,9361,35105,37444,10564,5265,9481,64773,16900,42050,37448,42312,9362,37449,10836,36 +3160 DATA 19017,4676,37449,18724,8778,9362,16914,16970,18514,48963,38056,2344,9361,34853,18724,9362,37025,74 +3170 DATA 4242,18729,18722,8778,18577,37449,10568,10529,34081,65425,8770,21061,34890,21128,9362,37449,9492,17 +3180 DATA 18980,9282,33865,18576,4644,18706,37410,37012,43156,28480,18729,33928,9488,35106,37156,18724,21666,42 +3190 DATA 42121,18580,20754,9482,18761,33953,17556,17672,50466,32736,9362,20773,37450,9364,9289,9362,35081,68 +3200 DATA 4690,34081,9380,34977,37412,21012,10530,10405,26692,31720,37129,9288,18577,37410,35088,37448,21076,18 +3210 DATA 18561,20628,35080,20756,9362,34978,33352,34056,12946,49136,17572,4754,8778,8521,21066,8482,33954,36 +3220 DATA 34090,35362,21074,33954,37128,9476,10514,10321,12841,16122,10513,17481,35105,37924,35108,18964,10505,73 +3230 DATA 10312,9364,1156,10505,17573,18514,17481,17034,10564,24572,16970,10532,9354,8850,9361,4257,21074,18 +3240 DATA 17042,37153,43090,17572,10512,1353,10530,37969,6674,45053,5264,16913,18513,17441,37130,42260,33924,36 +3250 DATA 37897,9364,17033,37448,33354,21008,16969,8836,6308,8126,41253,10564,4740,37514,17568,2210,10537,73 +3260 DATA 8866,37410,10512,9253,10532,37194,10532,37929,39490,44031,5268,16937,42025,9296,4682,42249,21072,18 +3270 DATA 37961,17476,4682,37521,17474,9361,16914,8850,3369,6127,18721,10562,2370,18565,18705,18596,33930,36 +3280 DATA 17042,4754,17553,18500,4392,37410,10568,17481,52370,22015,8778,33833,21012,9512,9290,4361,10513,73 +3290 DATA 10313,18505,37154,34066,18962,17481,4642,43298,52292,42495,38036,10564,33953,34962,17040,19026,21066,18 +3300 DATA 17698,9508,9289,20644,37188,4756,17481,4681,60713,2750,16929,16904,20756,8772,10277,37153,33936,36 +3310 DATA 34953,37000,18724,9481,8745,18498,37522,42132,46656,21239,5194,38053,33954,18706,37512,9364,21066,73 +3320 DATA 4644,2597,8722,34850,37952,9480,9289,2337,64661,42175,41252,8520,10500,4644,17445,16930,2193,18 +3330 DATA 42129,41104,35144,9544,16682,36946,18724,21066,64802,2735,5257,35345,37032,41288,4752,10377,21026,37 +3340 DATA 586,19013,9250,16933,5265,2697,9361,42121,65172,20565,8786,20554,18949,5125,9290,37458,17556,72 +3350 DATA 43297,4232,37513,10384,8772,42018,37444,4788,22049,43819,17583,1313,8528,18768,18721,17537,10528,37 +3360 DATA 4228,9490,2082,33346,18706,4425,18706,18431,48458,32586,5119,43156,38026,1162,4228,4372,16917,18 +3370 DATA 18985,18593,41620,10516,1092,41476,58532,44527,41491,32234,22525,16961,528,20752,18985,18985,35138,72 +3380 DATA 1090,33300,17474,16930,20625,2385,63753,24509,21887,55165,14190,5162,43173,17482,8514,8514,9257,37 +3390 DATA 20777,21665,10376,5192,35402,42052,48804,23403,54751,60911,65021,8832,16962,10528,35369,17416,37508,16 +3400 DATA 33924,33044,34066,41106,9248,18706,28434,63149,32762,37173,30634,18517,5161,33941,4164,4773,18513,74 +3410 DATA 21073,21570,20552,5380,17045,4644,48033,41218,38573,43692,44765,1315,8836,20546,19080,18568,1284,33 +3420 DATA 2306,297,2705,18513,10304,41281,12244,0,18811,10773,64373,20619,18513,34089,36946,8738,20649,20 +3430 DATA 41129,21632,40994,33412,34058,2580,2802,1152,4628,21157,55251,35374,1284,10372,9508,17556,34050,66 +3440 DATA 2564,8746,5444,5202,20560,20808,1001,8256,42089,21834,64173,8347,20562,37137,34962,34882,10280,20 +3450 DATA 20817,34881,16402,41224,2698,33829,692,2120,27304,43601,22379,38207,2696,17570,8772,9480,17730,33 +3460 DATA 1058,8852,10916,2597,20512,21136,33018,33024,38052,27284,61149,16571,40994,37396,18728,37029,4116,74 +3470 DATA 21129,37921,32776,20544,2709,9221,94,4128,11712,55973,56795,2654,5444,18753,9282,8720,19106,17 +3480 DATA 2084,16522,10914,650,41026,37544,8246,16932,42261,46932,46902,20501,16401,9236,35113,33858,8456,68 +3490 DATA 41617,5392,17417,21584,5385,17474,2143,4240,6944,60117,48618,1366,10914,17057,4242,21140,33954,18 +3500 DATA 2052,8261,37028,258,16464,10516,13,33824,54596,23978,28543,43051,32772,10500,19012,2081,21001,72 +3510 DATA 9553,35472,1280,21588,35461,17568,23,8201,46226,60282,48890,642,10921,16552,8457,8842,2212,17 +3520 DATA 16386,4133,43093,128,20520,51466,16911,35144,27304,55973,30047,21589,16384,10821,33874,18464,20737,34 +3530 DATA 10921,41608,640,43605,642,37457,4101,8200,39234,63197,23541,33026,10922,36880,10368,1354,33364,4 +3540 DATA 33028,1058,10282,16648,21524,58500,131,17698,21845,44475,27582,10793,33792,1354,16661,20496,5153,41 +3550 DATA 5201,43144,16704,5157,32929,18514,32779,10244,27304,55253,23295,32834,4778,10272,35360,1346,8842,64 +3560 DATA 41092,290,2581,8512,21770,58632,9221,16724,21077,15871,48621,10900,40960,17034,4245,20500,18464,21 +3570 DATA 1297,10756,20640,17429,2080,53841,65,10754,21842,61437,24251,16416,1365,5200,41536,34114,4746,34 +3580 DATA 43042,16552,517,34976,42314,58500,37378,18596,54613,61421,11950,2709,43136,16642,5141,10248,17424,8 +3590 DATA 324,5377,21672,9477,16,59689,129,9490,60074,61183,39295,20488,597,5204,16704,16721,37541,34 +3600 DATA 43529,41044,2,36946,21834,29250,18449,18501,32085,61439,9686,2725,43008,16514,2581,2562,8,68 +3610 DATA 162,1282,43688,17672,8736,59689,512,37522,65196,61405,38783,41232,682,5416,20640,20820,43681,40 +3620 DATA 21768,43048,2,34849,18570,46148,20642,43553,63402,65023,10107,1061,21508,16453,33285,1024,10,1 +3630 DATA 32849,322,10920,21130,37152,61714,1028,42133,32726,55295,19326,43336,338,5392,5288,20821,43680,84 +3640 DATA 5378,43528,16386,1056,9365,43552,20661,10529,65525,64989,38879,530,43520,16418,8705,33280,10,2 +3650 DATA 41044,162,35496,20618,37448,20810,34121,21844,56831,61439,8826,43332,170,5449,18602,5205,43680,40 +3660 DATA 1281,43528,4098,34080,18722,43524,21138,19081,65535,23421,38573,16402,21760,41476,8704,41088,10,1 +3670 DATA 20564,161,41640,10250,33300,59560,19818,53842,32699,61167,19447,5448,85,2385,34986,1322,10912,42 +3680 DATA 2305,20996,2050,17056,10561,29957,43653,60052,56319,32703,9949,8741,43656,40964,8704,20480,16389,0 +3690 DATA 8340,2217,8521,2053,17450,62544,46352,64165,65278,63483,35775,18576,37,5456,34986,682,5456,85 +3700 DATA 35393,16896,17440,20816,34945,47754,26660,64853,44887,24319,22525,4362,21826,16389,8704,21504,16389,0 +3710 DATA 8212,2218,2181,2565,20756,28964,17729,22363,65533,63423,9149,42145,40,38224,34986,340,5456,21 +3720 DATA 34113,8704,8720,41040,8736,31305,43284,65014,65463,65006,22381,4682,43665,2,8704,41986,16388,32 +3730 DATA 4100,34962,18594,2693,37957,59682,9378,65449,48125,65535,34299,18576,10,21844,34901,4240,5458,5 +3740 DATA 41553,8736,516,9232,8840,29832,18697,32746,65535,48127,10911,33317,43680,0,8832,16964,16384,80 +3750 DATA 2308,32906,10320,16545,18513,63781,43600,61434,32731,61311,44919,5268,10,21845,2069,5137,5461,5 +3760 DATA 8273,5152,33026,5380,34058,27208,21157,48125,61183,64475,6125,41289,21840,0,16544,16708,16384,16 +3770 DATA 34052,41226,10792,41000,20768,62610,21780,65279,65535,65534,45019,2578,133,21845,5381,1041,4693,69 +3780 DATA 4129,1088,32898,1346,33941,26916,43337,61375,65501,46591,20351,9380,21800,0,16424,20612,16640,16 +3790 DATA 17544,37129,4648,10248,10304,62793,43602,65527,48127,57279,39901,18760,69,21845,2689,545,5193,65 +3800 DATA 4129,17444,16512,17058,17685,62610,60074,64511,65279,27133,16255,37,21776,512,8212,10376,16674,20 +3810 DATA 17028,4418,5157,2056,10528,59689,64165,32509,65463,65519,49022,21832,32805,10410,35137,16930,5128,1 +3820 DATA 2065,17,16656,20769,17477,53826,64170,65471,57343,61181,16123,533,21833,33040,8712,2056,16545,84 +3830 DATA 8772,21636,1093,1156,34952,62612,48469,57327,65535,65471,48623,43336,528,5189,32930,8512,2570,1 +3840 DATA 35089,528,20736,20497,20753,43298,65173,65535,64445,57339,23483,1106,21570,16648,5128,17418,8480,36 +3850 DATA 8256,36930,84,1348,35364,57876,65387,65021,32751,65007,55919,20773,8341,5157,16673,2208,34953,0 +3860 DATA 33290,1160,10754,8209,8513,60065,61397,57311,57343,49149,44027,35403,38184,16704,5252,8709,8738,42 +3870 DATA 10401,41488,32912,35392,18964,21642,32727,65535,63229,63359,53238,9367,66,1034,16401,32912,34816,0 +3880 DATA 520,2117,4612,8202,37024,58708,65003,65279,65535,65527,61421,18727,21801,20816,2372,5186,8874,18 +3890 DATA 36930,8448,16545,4768,9477,51745,65535,30651,32735,48127,27518,4695,33298,2,8208,16649,2048,64 +3900 DATA 2312,1108,5124,18437,21672,43338,30710,65535,62975,57215,65519,41706,10404,43668,2690,9248,16677,21 +3910 DATA 8225,20481,16529,33360,33058,37546,57215,65535,49147,47095,47071,38391,33034,64,16424,137,4624,0 +3920 DATA 33412,1352,4608,10242,10820,42257,61439,48111,65215,65023,56319,9687,10832,37394,2304,43552,34884,36 +3930 DATA 10257,8192,34901,17064,18729,21578,56303,65275,65535,24510,46555,18943,32901,136,8266,5,8448,16 +3940 DATA 576,1173,256,4096,37442,8868,44797,65534,61403,65519,19455,37815,5416,21538,512,9360,33877,2 +3950 DATA 4106,36864,21540,17557,9364,38025,20478,57339,64511,65019,43709,9455,40997,256,43177,260,4352,72 +3960 DATA 17568,681,128,37376,19016,10578,12223,63453,32511,65407,49847,18943,3016,9258,4,43040,16420,2 +3970 DATA 4105,43008,37386,164,37009,16932,20474,65258,65526,57327,43359,37501,22514,32896,9504,1157,5248,40 +3980 DATA 33344,548,160,10752,10826,23189,39933,65460,65535,65533,33325,9455,3773,2597,2,16400,16394,1 +3990 DATA 2069,8320,21506,32853,16656,33966,24314,65225,28607,32511,59735,19135,24350,41088,43592,2372,4768,68 +4000 DATA 41600,33802,72,9472,37957,10562,40890,46482,64495,63423,53285,37039,7750,2090,32,40960,4,17 +4010 DATA 36,4384,17664,4178,18696,42243,16372,60709,65531,24559,58005,9533,49047,16640,37130,1172,9360,0 +4020 DATA 37377,16392,4178,16896,4177,19017,32757,60072,61438,47101,62498,21599,8011,1060,1088,36864,32772,36 +4030 DATA 72,2626,33288,2196,42242,5921,63466,38037,32511,11775,59716,35119,49059,20608,8201,1353,5408,0 +4040 DATA 10498,16400,2114,40962,2088,19531,65001,43298,65018,19327,47625,53838,14309,554,2336,8192,16393,21 +4050 DATA 32784,1156,41232,2720,42306,40789,65490,43595,65462,4853,64850,35483,40937,18432,16386,554,576,0 +4060 DATA 4673,20512,2049,16388,53256,24571,65492,2815,56169,19119,65269,53543,16343,658,4776,18560,10245,34 +4070 DATA 16388,258,33060,4368,41633,16383,57161,32767,65514,62815,65503,59989,36343,36928,32770,4,33104,0 +4080 DATA 1360,9288,9216,1090,62468,31727,64466,65502,65535,65533,56829,57483,24567,532,4640,9360,2049,20 +4090 DATA 36865,32768,74,40968,63632,65407,65316,65535,31679,65279,65535,47698,3069,10369,16393,1,8740,1 +4100 DATA 1060,2378,18688,578,55810,57338,65097,63223,65517,28607,64507,64805,12223,36,2368,19108,128,16 +4110 DATA 8320,8192,145,18448,30888,65524,61075,49150,57343,65519,48863,65352,22271,21121,8210,0,9225,1 +4120 DATA 33289,548,37892,130,63489,63357,64815,65535,65023,65531,32767,60821,3855,40,33280,18452,288,36 +4130 DATA 2080,18560,288,4616,61732,24559,64093,64991,65407,31743,47095,65506,38878,38144,2194,320,18434,0 +4140 DATA 8322,9,8201,16545,29696,49151,54448,57341,49133,65279,24575,65528,9135,74,8192,9225,584,73 +4150 DATA 520,18720,2624,1032,57673,32255,62187,65535,61439,57279,14205,57341,38887,20992,594,32896,8192,0 +4160 DATA 18465,2,16402,20610,18432,65467,54657,64991,64511,65517,22527,64383,2813,170,18432,9234,1170,9 +4170 DATA 136,37448,4224,1040,20626,61421,22295,57335,49085,65535,38383,65535,42431,18944,138,64,8192,32 +4180 DATA 37378,0,33316,32900,41472,65490,56495,65534,25983,63485,60414,32751,2815,37,37408,35076,2340,9 +4190 DATA 32,9362,4097,4640,18516,31317,47423,65021,31471,65267,64191,61435,42351,37520,4,8208,16384,0 +4200 DATA 9348,0,33352,16388,8450,64853,58111,49014,64251,49084,64891,64383,2490,2,37440,580,585,36 +4210 DATA 32801,18724,4098,2336,33808,58708,34299,63451,64511,61438,32599,49151,42346,21672,9,2048,34816,0 +4220 DATA 4608,0,33056,20484,4421,43336,22399,44399,49151,24575,57301,45055,2218,513,18720,16658,8338,8 +4230 DATA 32836,37156,9224,1312,16400,10789,8157,43868,65503,47071,65514,43447,21850,146,9,4096,512,2 +4240 DATA 1040,1024,64,16386,2690,54400,65534,51570,65018,19959,64509,22271,41557,21512,37440,584,34833,32 +4250 DATA 8449,73,35081,2192,8200,20757,32745,37609,61439,44029,65530,43710,5290,289,18,16384,64,8 +4260 DATA 72,8704,8192,41472,2338,17472,60917,42883,57308,38399,57214,10927,41233,8196,8448,1058,37124,0 +4270 DATA 9216,145,1169,146,16384,37129,65450,11871,61183,58743,63487,19115,19018,2642,1057,4360,1057,4 +4280 DATA 34,18436,32768,9216,4777,9248,65194,22879,65492,59887,65503,42157,10916,16385,16648,16386,16384,32 +4290 DATA 18696,512,4388,264,32772,34954,48468,62839,26538,64171,32759,2389,17481,2388,4160,1088,580,2 +4300 DATA 2,32930,0,36929,5184,8480,60240,43773,44373,32343,24063,20779,10898,32769,1028,17,4097,16 +4310 DATA 8768,4096,9352,1040,16644,35397,59978,22527,27467,65429,28671,33941,20820,4650,16528,18688,16528,2 +4320 DATA 8,521,32769,8452,2065,8232,43684,45055,21678,61413,23419,43557,35402,32900,1028,68,1024,32 +4330 DATA 18561,4128,9360,64,8512,35457,21522,64989,42298,64490,22014,4233,21649,9233,4160,4097,8457,4 +4340 DATA 16,16512,2,17426,1042,8228,43332,65526,18679,65276,22207,18978,2346,290,530,272,32,1 +4350 DATA 2308,1033,37408,4352,41216,17552,20497,57341,43999,65518,38255,21652,21157,32777,8192,9220,17410,16 +4360 DATA 8256,8256,4,32840,2084,4610,35490,64426,19455,48787,10927,8457,38034,4644,33344,32832,4160,0 +4370 DATA 1041,530,4673,8706,33024,41128,20500,65389,57342,61349,17749,19026,18729,128,2066,2064,264,34 +4380 DATA 33024,4096,16400,2080,2066,2562,19009,64938,32631,64488,4693,38021,37444,18474,8448,258,34818,0 +4390 DATA 4164,1088,2308,33033,41536,20648,37140,56148,38911,32730,18581,8490,9385,128,66,36864,544,8 +4400 DATA 16,16402,16448,2112,2052,34050,1090,62793,12287,24565,41557,18960,18706,37413,17424,548,16384,0 +4410 DATA 8705,256,4113,8708,41617,10280,20744,21845,17851,22271,1029,37189,4772,8,0,129,4164,34 +4420 DATA 32832,2056,1280,33,2048,17730,33825,54564,53758,44030,21162,10770,42057,9282,2338,18432,512,0 +4430 DATA 9220,8256,66,18560,41554,2320,4426,43593,54334,43775,2050,16708,19090,260,16392,8,32785,8 +4440 DATA 272,514,8200,530,2052,20642,41984,43154,62805,23279,17060,43537,4388,18449,514,578,2176,0 +4450 DATA 2,16400,33280,36864,8480,42244,2218,9514,64143,19451,2313,2368,17481,68,4160,36864,16388,36 +4460 DATA 18496,2176,4241,1168,35346,2216,20992,21073,65187,6142,37026,21012,658,18689,32784,1040,544,0 +4470 DATA 520,2,0,8196,64,21057,8341,42122,65448,24447,2568,42146,10276,16,2305,128,4096,1 +4480 DATA 32770,4368,33826,32832,20756,33940,18976,31017,49109,49151,41122,2184,33417,4676,68,8194,137,16 +4490 DATA 4384,32768,8448,2576,1024,10496,4234,2626,61434,65519,1280,42274,9252,16384,8192,528,17408,4 +4500 DATA 0,1092,8,16388,32850,41556,19024,22357,48125,65023,20567,4680,129,1161,2312,132,32,0 +4510 DATA 17426,8192,2114,257,4352,2176,20741,18834,44927,61310,1295,18562,18986,36896,66,36865,516,1 +4520 DATA 128,272,512,36928,36,21033,33832,58596,21487,65517,36927,37456,128,514,16384,1024,4224,16 +4530 DATA 4096,34817,16520,16,8704,33920,43330,59962,44287,32762,763,9348,36885,8328,1040,144,32,4 +4540 DATA 530,136,0,1028,73,4117,38164,62604,43710,57298,37375,18704,576,2048,260,16388,16386,0 +4550 DATA 128,8194,9234,8192,17408,42304,8354,65363,2735,64341,1983,33860,8210,544,8193,1025,1024,0 +4560 DATA 36896,1088,64,129,4368,2068,54536,65186,8875,65364,12271,4353,2048,2,64,64,32840,36 +4570 DATA 2,32784,256,33808,4,41281,42066,57300,35146,64680,16381,8208,585,16400,1040,36880,2048,0 +4580 DATA 528,2048,18468,8192,17472,2568,14980,63465,42,27298,65023,2626,32768,1152,8192,514,256,0 +4590 DATA 36864,260,0,2114,4352,41121,17704,48638,35154,60032,65535,16389,4130,4,258,0,8210,9 +4600 DATA 130,8256,1153,528,16457,46084,43842,24570,8197,38164,61407,4399,264,36864,32832,4160,2048,0 +4610 DATA 1040,2064,8200,0,1024,65296,18677,42879,2602,43009,65014,33919,34816,288,2064,33800,576,0 +4620 DATA 8192,513,32,16385,37124,22338,62815,23551,8256,21160,65533,12285,66,8,0,256,8,17 +4630 DATA 130,32776,2304,2184,16,2440,59904,43743,2698,8193,49138,65503,517,2050,8193,65,16384,0 +4640 DATA 2064,8258,16388,0,21057,42434,64874,21883,16528,33316,61140,49279,36943,16896,2320,16400,4226,0 +4650 DATA 33280,512,4128,16930,16,720,32656,2719,4612,2176,65445,10935,30,64,0,4096,32,36 +4660 DATA 4,0,264,0,37380,43396,65494,9399,145,16405,65096,17661,2335,0,4,1026,1024,0 +4670 DATA 8256,18576,2050,2048,128,19168,57321,341,9216,256,31378,22015,93,4100,17472,64,32772,0 +4680 DATA 1024,4,16896,32914,9248,21890,65018,19030,290,2081,62624,56319,16447,33056,0,16,8321,0 +4690 DATA 18,513,32,8192,32776,43984,49149,37013,4096,16904,58632,32703,4639,0,8,4100,2080,36 +4700 DATA 256,8256,1,1024,2304,32640,44991,554,33348,128,34945,61431,151,2050,9344,512,0,0 +4710 DATA 4096,2064,9352,137,16450,65412,44031,21650,16,4100,21024,65534,31,33312,0,32769,0,0 +4720 DATA 32776,0,0,0,4096,61344,22519,5,18433,1056,43010,65278,32813,0,8,8256,16648,4 +4730 DATA 578,33028,0,8192,528,64265,22269,4752,132,16640,32784,61420,2311,8,128,1040,2112,0 +4740 DATA 0,4160,37448,548,16386,54912,35775,32770,32,9,8452,32765,85,4352,18433,4,0,32 +4750 DATA 36864,0,0,32768,1088,54304,5119,4424,9216,4096,2049,65278,32789,0,16,0,2,1 +4760 DATA 1040,520,1,4096,4096,58626,9726,1,260,288,33312,61374,8194,32,256,8448,8224,0 +4770 DATA 130,8320,9360,1089,32784,59664,1519,9252,65,18441,0,32760,1029,17416,32772,64,512,8 +4780 DATA 0,33,0,8,260,54336,8959,1,4096,0,132,32756,289,0,2048,2056,2,0 +4790 DATA 8224,2048,2,0,2049,49156,2427,128,16,256,18465,48616,0,258,544,32768,4160,1 +4800 DATA 1028,32776,37440,16640,16384,33280,639,18440,16900,18500,0,28581,32768,8192,2,1,16,32 +4810 DATA 256,8448,16,4164,576,37008,16542,2,128,0,4352,38184,4104,64,16384,576,1024,8 +4820 DATA 0,65,0,0,0,32770,676,576,4097,0,36,10832,128,2048,64,8208,0,2 +4830 DATA 8210,2064,9216,0,8200,32768,42,8192,16,8721,513,37505,0,16,1026,0,16642,0 +4840 DATA 256,0,273,2,2048,2048,8529,2057,512,0,4224,9512,1056,32770,0,0,32,0 +4850 DATA 0,16388,0,35088,128,72,10,576,8322,128,8,2048,16392,8448,8224,16898,0,0 +4860 DATA 34884,1152,32768,0,32,16385,16,0,0,4100,32769,256,0,0,512,32,4096,32 +4870 DATA 0,0,4128,0,8,1024,9280,32770,32,1,1056,4,2,64,0,4096,1028,9 +4880 DATA 0,8208,516,0,8194,0,4,4240,2048,16896,256,8256,512,2056,8,8,64,0 +4890 DATA 8466,516,0,17476,1024,64,0,0,0,64,16388,0,8192,2,4096,513,0,0 +4900 DATA 0,0,1,1,0,32784,37120,1024,516,16,0,0,64,0,129,0,0,0 +4910 DATA 0,4224,16512,0,0,4100,64,68,32897,8192,32,1028,16,0,0,32768,32776,0 +4920 DATA 33824,0,4128,0,256,1025,0,0,0,2048,514,33025,0,16896,0,128,4352,0 \ No newline at end of file diff --git a/samples/sample.bodymass.txt b/samples/sample.bodymass.txt new file mode 100644 index 0000000..6f6cb59 --- /dev/null +++ b/samples/sample.bodymass.txt @@ -0,0 +1,32 @@ +10 REM A Simple Body Mass Index Calculator. +20 REM Written by Tim Dwyer on 5 July 2011. +30 HOME +40 DIM height +50 DIM weight +60 DIM bmiCalc +70 DIM keepGoing$ +80 PRINT "***************************" +90 PRINT "* *" +100 PRINT "* Simple BMI Calculator *" +110 PRINT "* *" +120 PRINT "***************************" +130 PRINT "" +140 PRINT "" +150 INPUT "Input your height (inches): "; height +160 INPUT "Input your weight (lbs): ";weight +170 bmiCalc = (weight/(height*height))*703 +180 PRINT "" +190 PRINT "Your BMI is ";bmiCalc +200 PRINT "" +210 PRINT "" +220 INPUT "Calculate another? (y/n): ";keepGoing$ +230 IF keepGoing$ = "y" or keepGoing$ = "Y" GOTO 130 +240 IF keepGoing$ = "n" or keepGoing$ = "N" GOTO 300 +250 IF keepGoing$ <> "y" or keepGoing$ <> "Y" GOTO 270 +260 IF keepGoing$ <> "n" or keepGoing$ <> "N" GOTO 270 +270 PRINT "" +280 PRINT "That is not a valid selection." +290 GOTO 200 +300 PRINT "" +310 PRINT "Goodbye!" +320 END diff --git a/samples/sample.boys_surface.txt b/samples/sample.boys_surface.txt new file mode 100644 index 0000000..6368201 --- /dev/null +++ b/samples/sample.boys_surface.txt @@ -0,0 +1,25 @@ +10 REM Boy's Surface +20 REM From the book "Topologicon" by Jean-Pierre Petit +100 PI=3.141592:P3=PI/3:P6=PI/6:P8=PI/8 +110 HGR : POKE 49234,0 +120 HCOLOR=3 +130 FOR MU = 0 TO PI STEP 0.1 +140 D=34+4.79*SIN(6*MU-P) +150 E=6.73*SIN(3*MU-P6) +160 A=D+E +170 B=D-E +180 AL=(P8)*SIN(3*MU) +190 C1=A*A-B*B +200 C2=SQR(A*A+B*B) +210 CM=COS(MU) +220 SM=SIN(MU) +230 FOR TE=0 TO 6.282 STEP .03 +240 X1=C1/C2+A*COS(TE)-B*SIN(TE) +250 Z1=C2+A*COS(TE)+B*SIN(TE) +260 REM KOORDINATEN +270 X=X1*CM-Z1*SIN(AL)*SM +280 Y=X1*SM+Z1*SIN(AL)*SM +300 REM ZEICHNUNG +310 HPLOT 140+X,96+Y +320 NEXT TE +330 NEXT MU diff --git a/samples/sample.charset.txt b/samples/sample.charset.txt new file mode 100644 index 0000000..af2c474 --- /dev/null +++ b/samples/sample.charset.txt @@ -0,0 +1,23 @@ +100 PR#0 : HOME +110 PRINT "80 Col Firmware Inactive" +120 GOSUB 1000 +130 PRINT : PRINT "Press any key "; : GET A$ + +200 PR#3 : PRINT CHR$(17); : HOME +210 PRINT "80 Col Firmware Active" +220 GOSUB 1000 + +999 END + +1000 PRINT : PRINT "Normal" : NORMAL : GOSUB 2000 : NORMAL +1010 PRINT : PRINT "Inverse" : INVERSE : GOSUB 2000 : NORMAL +1020 PRINT : PRINT "Flash" : FLASH : GOSUB 2000 : NORMAL +1030 PRINT : PRINT "Mousetext" : PRINT CHR$(27);CHR$(15); : GOSUB 2000 : PRINT CHR$(14);CHR$(24) +1040 RETURN + +2000 FOR I = 32 TO 127 STEP 32 +2010 : FOR J = 0 TO 31 +2020 :: PRINT CHR$(I+J); +2030 : NEXT : PRINT +2040 NEXT +2050 RETURN \ No newline at end of file diff --git a/samples/sample.connections.txt b/samples/sample.connections.txt new file mode 100644 index 0000000..3419d34 --- /dev/null +++ b/samples/sample.connections.txt @@ -0,0 +1,9 @@ +10 TEXT : HOME : INPUT "NUMBER OF POINTS:";A: HCOLOR= 3 +20 HGR : POKE -16302,0 +30 FOR T1 = 0 TO (2 * 3.14) - .001 STEP ((2 * 3.14) / A) +40 FOR T2 = (T1 + (2 * 3.14) / A) TO (2 * 3.14) - .001 STEP (2 * 3.14) / A +50 HPLOT ( COS (T1) * 95 + 127),( SIN (T1) * 95 + 95) TO ( COS (T2) * 95 + 127),( SIN (T2) * 95 + 95) +60 NEXT +70 NEXT +80 GET A$ +90 GOTO 10 diff --git a/samples/sample.default.txt b/samples/sample.default.txt new file mode 100644 index 0000000..eef2cbd --- /dev/null +++ b/samples/sample.default.txt @@ -0,0 +1 @@ +10 PRINT "Hello World" diff --git a/samples/sample.february.txt b/samples/sample.february.txt new file mode 100644 index 0000000..8308b1a --- /dev/null +++ b/samples/sample.february.txt @@ -0,0 +1,25 @@ +1 REM 25 THINGS +2 TEXT +3 HOME +4 GR +5 LET E = 0 +6 LET V = 100 +7 HTAB V/10 - 1 +8 VTAB 23 +9 COLOR = V/100 +10 FOR L = 0 TO V + E +11 LET V = E +12 LET E = L/10 +13 VLIN 20,20+(L/100)*20 AT (E)+10 +14 VLIN 20,20+(L/100)*20 AT 30-(E) +15 VLIN (SIN((L+27.1)/10)*7)+12,20 AT L/5+10 +16 LET E = V +17 LET E = E + 1 +18 IF E = 4 THEN GOSUB 21 +19 NEXT +20 END +21 LET V = INT(L/E)+1 +22 PRINT V" "; +23 LET E = 0 +24 RETURN +25 REM BY API diff --git a/samples/sample.gaussian.txt b/samples/sample.gaussian.txt new file mode 100644 index 0000000..3bcc5b6 --- /dev/null +++ b/samples/sample.gaussian.txt @@ -0,0 +1,47 @@ +5 rem Plot Gaussian distribution in two dimensions +10 text: home: PRINT "Std. Dev. = ";: input s1 +20 hgr: hcolor = 3 +30 w = 279: h = 159 +40 w0 = w - 100: w1 = w0/10 +45 h1 = h - 100: h2 = h - 60 +50 k = 0.5: m = 1 / (2 * 3.14159265 * s1 * s1) +60 for i = 0 to 10 step k +70 x = 10 * i + 1: y = 10 * i + h1 +75 hplot x,y +80 for j = 0 to w0 step 1 +85 j1 = 10 * j / w0 +90 d1 = abs(5 - i) +100 d2 = abs(5 - j1) +110 r2 = (d1*d1+d2*d2)/(2*s1*s1) +120 g = exp(-r2)/(2*3.14159*s1*s1) +130 a = int((h2 * g)/ m) +140 x = 10 * i + w1 * j1 + 1 +150 y = 10 * i + h1 - a +160 hplot to x,y +170 if (i = 0) goto 265 +175 if (j = w0) goto 190 +180 j2 = int(j/10): if ((j/10) <> j2) goto 290 +190 d1 = abs(5 - i + k) +200 d2 = abs(5 - j1) +210 r2 = (d1*d1+d2*d2)/(2*s1*s1) +220 u = exp(-r2)/(2*3.14159*s1*s1) +225 a1 = int((h2 * u)/ m) +230 x1 = 10 * (i - k) + w1 * j1 + 1 +240 y1 = 10 * (i - k) + h1 - a1 +245 rem if (y <= y1) goto 290 +250 hplot to x1,y1 +260 hplot x,y +265 if (j = 0) goto 310 +270 if (i < 10) goto 290 +275 if (j = w0) goto 295 +280 j2 = int(j/10): if ((j/10) = j2) goto 295 +290 hcolor = 0 +295 hplot to x,10 * i + h1 +300 hcolor = 3 +305 hplot x,y +310 next j +320 next i +330 hplot w+1,h: hplot to 100+1,h: hplot to 0+1,h1 +340 vtab 21: print "Gaussian (standard deviation = ";s1;")" +350 print "Plot from -5.0 to + 5.0" +360 print "Peak value = "m diff --git a/samples/sample.hacker.txt b/samples/sample.hacker.txt new file mode 100644 index 0000000..7135315 --- /dev/null +++ b/samples/sample.hacker.txt @@ -0,0 +1,48 @@ + 5 REM http://www.geocities.com/mmphosis/apple2/contest/2007/old-computer-challenge.html + 10 GR + 20 POKE 49234,0 : rem fullscreen + 30 COLOR= 15 + 40 FOR I = 0 TO 39 + 50 VLIN 0,47 AT I + 60 NEXT + 100 COLOR= 5 + 110 S = 21 + 120 W = S + 130 H = 27 + 140 X = INT ((40 - W) / 2) + 150 Y = INT ((48 - H) / 2) + 160 D = INT (W / 3) + 161 DX = D + 170 Y2 = Y + H + 180 X2 = X + W + 200 FOR I = 0 TO 3 + 210 VLIN Y,Y2 AT X + I * D + 220 NEXT + 240 D = INT (H / 3) + 250 FOR I = 0 TO 3 + 260 HLIN X,X2 AT Y + I * D + 270 NEXT + 280 YH = INT (D / 2) + 281 YM = Y + H - YH + 290 XH = INT (DX / 2) + 300 COLOR= 0 + 310 FOR I = 0 TO 2 + 320 YY = YM + 330 XX = X + XH + I * DX + 340 GOSUB 500 + 350 NEXT + 400 YY = YY - D + 410 GOSUB 500 + 420 YY = YY - D + 430 XX = XX - DX + 440 GOSUB 500 + 450 K = PEEK ( - 16384) + 460 IF K < 128 THEN 450 + 470 K = PEEK ( - 16368) + 480 TEXT : HOME + 490 END + 500 VLIN YY + 1,YY - 2 AT XX + 510 VLIN YY + 1,YY - 2 AT XX + 1 + 520 VLIN YY,YY - 1 AT XX - 1 + 530 VLIN YY,YY - 1 AT XX + 2 + 540 RETURN diff --git a/samples/sample.hangman.txt b/samples/sample.hangman.txt new file mode 100644 index 0000000..bfbecf8 --- /dev/null +++ b/samples/sample.hangman.txt @@ -0,0 +1,613 @@ +100 REM ***HANGMAN** +120 REM BY MIKE GLEASON, 1986, 2011 +140 REM +160 REM ==WELCOME SCREEN== +180 TEXT : HOME :SW = PEEK (33):ES$ = "": GG = 1: SND = 1: DD = 0.040: JY = 0 +188 DD = 0.0010 : SND = 0: GOTO 380: REM Hack to work in the JavaScript emulator +200 IF (GG < 1) THEN 380 +220 IF (PEEK(103) <> 1) THEN 280 +240 IF (PEEK(104) = 64) AND (PEEK(16384) = 0) THEN 380 +260 IF (PEEK(104) = 96) AND (PEEK(24576) = 0) THEN 380 +280 PRINT "THIS VERSION OF HANGMAN IS TOO BIG" +300 PRINT "TO RUN WITHOUT HELP FROM YOU.":PRINT +320 PRINT "PLEASE TYPE THE FOLLOWING:":PRINT +340 PRINT "NEW":PRINT "POKE 103, 1":PRINT "POKE 104, 64":PRINT "POKE 16384, 0":PRINT "RUN HANGMAN" +360 END +380 VTAB 12:I = SW / 2 - 6: HTAB I: PRINT "_ _ _ _ _ _ _"; +400 GOSUB 13800 : REM INIT SOUND +420 D = 1: GOSUB 800: HTAB I + 8: PRINT "M"; +440 D = 1: GOSUB 800: HTAB I + 4: PRINT "N";: HTAB I + 12: PRINT "N"; +460 D = 1: GOSUB 800: HTAB I + 6: PRINT "G"; +480 D = 1: GOSUB 800: HTAB I + 2: PRINT "A";: HTAB I + 10: PRINT "A"; +500 D = 1: GOSUB 800: HTAB I + 0: PRINT "H"; +520 D = 2: GOSUB 800: HTAB I + 0: FLASH : PRINT "H A N G M A N": NORMAL : PRINT +540 D = 2: GOSUB 800 +560 A$ = "(C) 1986, 2011 by Mike Gleason" +580 I = SW / 2 - ( LEN (A$) - 0) / 2 +600 HTAB I: PRINT A$; +620 A$ = "Loading, please wait..." +640 I = SW / 2 - ( LEN (A$) - 3) / 2 +660 VTAB 23: HTAB I: PRINT A$;: JY=1 +680 GOTO 1100 +700 : +720 : +800 REM ==DELAY SUBROUTINE== +820 REM Unfortunately, I don't know of a way to make this delay constant +840 REM across CPU speeds. For example, in an emulator, this code may +860 REM run too fast. You can try changing DD to modulate the speed. +880 IF ( PEEK (49152) > 127) THEN 940: REM SKIP DELAY UPON KEYBOARD INPUT +900 D = D - DD: IF D > 0 THEN 880 +920 GOTO 980 +940 A$ = CHR$ ( PEEK (49152) - 128) +960 IF (JY=1) THEN POKE 49168,0 +980 RETURN +1000 : +1020 : +1100 REM ==INITIALIZE PROGRAM== +1120 DIM GZ%(32) +1140 GOSUB 3200: REM SETUP LIMBS +1160 GOSUB 13200: REM LOAD WORDS +1180 GOSUB 2500: REM SETUP SCREEN +1200 PRINT "Shall I be [e]asy, " +1220 PRINT " [m]edium, " +1240 PRINT " or [h]ard on you? "; +1260 POKE 49168,0: REM CLEAR KEYB BUFFER +1280 GOSUB 1800 +1300 IF (A$ = "E") THEN EZ = 1: GOTO 1400 +1320 IF (A$ = "M") THEN EZ = 2: GOTO 1400 +1340 IF (A$ = "H") THEN EZ = 3: GOTO 1400 +1360 PRINT : GOTO 1200 +1400 REM ==GAME LOOP== +1420 HOME:VTAB 24 +1440 CHEET = 0 +1460 PRINT : GOSUB 2100 +1480 PRINT "Play again? (Yes/No) ";: GOSUB 1800 +1500 IF (A$ = "Y") THEN 1400 +1520 ES$ = "": GOTO 1620 +1600 REM ==CLEANUP AND EXIT== +1620 TEXT +1640 IF (ES$ = "") THEN 1720 +1660 GOSUB 14300: REM RING BELL +1680 PRINT : PRINT "* ERROR: ";ES$;"." +1700 END +1720 HOME +1740 PRINT "GOOD BYE." +1760 END +1800 REM ==GET 1 UPPERCASE CHAR== +1820 GET A$:A$ = LEFT$ (A$,1) +1840 IF (A$ = CHR$ (1)) THEN CHEET = 1: GOTO 1980 +1860 IF (A$ = CHR$ (27)) OR (A$ = CHR$ (3)) THEN 1600 +1880 A = ASC (A$) +1900 IF ( ASC ("A") < = A) AND (A < = ASC ("Z")) THEN 2020 +1920 IF (A < ASC ("a")) OR (A > ASC ("z")) THEN 1980 +1940 A$ = CHR$ (A - ( ASC ("a") - ASC ("A"))) +1960 GOTO 2020 +1980 GOSUB 14300: REM RING BELL +2000 GOTO 1820 +2020 RETURN +2040 : +2060 : +2100 REM ==GAME SUBROUTINE== +2120 GOSUB 3600: REM SETUP GRAPHICS +2140 GOSUB 9600: REM CHOOSE A SECRET WORD +2160 POKE 49168,0: REM CLEAR KEYB BUFFER +2180 NLIMBS = 0:GAMEOVER = 0 +2200 FOR I = 0 TO 30:GZ%(I) = 0: NEXT I +2220 HOME: VTAB 21 +2300 REM --GUESS LOOP-- +2320 GOSUB 7400: REM DISPLAY STATUS +2340 GOSUB 7700: REM GET A GUESS +2360 GOSUB 8100: REM CHECK GUESS +2380 IF GAMEOVER = 0 THEN 2300 +2400 RETURN +2420 : +2440 : +2500 REM ==SETUP SCREEN== +2520 TEXT : HOME : CB$ = "an" : CA$ = "ANIMAL" +2540 A$ = "Welcome to HANGMAN!": GOSUB 3000: PRINT : PRINT +2560 PRINT "You have been condemned for execution." +2580 PRINT "To escape this fate, you must guess" +2600 PRINT "the secret word (";CB$;" ";CA$;") by " +2620 PRINT "choosing letters from the alphabet." +2640 PRINT +2660 PRINT "The secret word's letters will be shown" +2680 PRINT "as dashes at first, and then will" +2700 PRINT "change to letters as you guess them." +2720 PRINT +2740 PRINT "With each incorrect guess, one body" +2760 PRINT "part will be added to the gallows." +2780 PRINT "Guess the secret word before all your" +2800 PRINT "limbs are hanging!" +2820 PRINT +2840 A$ = "Press any key to begin!": GOSUB 3000 +2841 POKE 49168,0: REM CLEAR KEYB BUFFER +2842 I=1: REM Initialize random number generator +2845 IF ( PEEK (49152) > 127) THEN 2860 +2848 I = I + 1 +2850 IF I > 127 THEN 2842 +2852 GOTO 2845 +2860 GET A$ +2863 L=RND(-I) +2880 HTAB 1: CALL - 868: REM ERASE STATUS MESSAGE +2900 RETURN +2920 : +2940 : +3000 REM ==PRINT CENTERED== +3020 HTAB (40 / 2 - LEN (A$) / 2) +3040 PRINT A$; +3060 RETURN +3080 : +3100 : +3200 REM ==SETUP LIMBS== +3220 DIM LIMBS$(11) +3240 LIMBS$(1) = "HEAD" +3260 LIMBS$(2) = "LEFT EYE" +3280 LIMBS$(3) = "RIGHT EYE" +3300 LIMBS$(4) = "NOSE" +3320 LIMBS$(5) = "MOUTH" +3340 LIMBS$(6) = "TORSO" +3360 LIMBS$(7) = "LEFT ARM" +3380 LIMBS$(8) = "RIGHT ARM" +3400 LIMBS$(9) = "LEFT LEG" +3420 LIMBS$(10) = "RIGHT LEG" +3440 LIMBS$(11) = "***HANGMAN***" +3460 RETURN +3480 : +3500 : +3600 REM ==SETUP GRAPHICS== +3620 IF (GG = 0) THEN 3680 +3640 HGR : GW=280 : GH=160 : REM THIS IS ALL FOR NOW +3660 GOSUB 3800: REM DRAW GALLOWS +3680 RETURN +3700 : +3720 : +3800 REM ==DRAW GALLOWS== +3820 IF (GG = 0) THEN 3980 +3840 HCOLOR=1:FOR I=GH-1 TO 152 STEP -1:HPLOT 0,I TO GW-1,I:NEXT I +3860 HCOLOR=3 +3880 FOR I=152 TO 148 STEP -1:HPLOT 70,I TO 210,I:NEXT I +3900 FOR I=80 TO 88:HPLOT I,10 TO I,152:NEXT I +3920 FOR I=10 TO 18:HPLOT 88,I TO 147,I:NEXT I +3940 FOR I=0 TO 7:HPLOT 80,48+I TO 110+I,18:NEXT I +3960 FOR I=147 TO 145 STEP -1:HPLOT I,18 TO I,30:NEXT I +3980 RETURN +4000 : +4020 : +4100 REM ==DRAW LIMB== +4120 IF (GG = 0) THEN 4180 +4140 ON NLIMBS GOSUB 4300, 4500, 4700, 4900, 5100, 5500, 5600, 5700, 5800, 5900 +4160 GOTO 4200 +4180 VTAB 21: HTAB 1: CALL -868: PRINT "Your ";LIMBS$(NLIMBS);" is now hanging!": +4200 RETURN +4220 : +4240 : +4300 REM ==DRAW HEAD== +4320 REM Note: It'd be quicker (and use less code) to just HPLOT out the +4340 REM circle by hand rather than calling my CIRCLE2 subroutine, but +4360 REM then the trigonometry lesson would be wasted. +4380 HCOLOR=2 +4400 REM HPLOT 126,30 TO 166,30 TO 166,70 TO 126,70 TO 126,30 +4420 RADIUS=20:CX=146:CY=50:FILL=0:GOSUB 6000 +4440 RETURN +4460 : +4480 : +4500 REM ==DRAW LEFT EYE== +4520 HCOLOR=6:HPLOT 137,43 TO 140,43 +4540 HPLOT 136,44 TO 141,44 +4560 HPLOT 137,45 TO 140,45 +4580 RETURN +4600 : +4620 : +4700 REM ==DRAW RIGHT EYE== +4720 HCOLOR=6:HPLOT 152,43 TO 155,43 +4740 HPLOT 151,44 TO 156,44 +4760 HPLOT 152,45 TO 155,45 +4780 RETURN +4800 : +4820 : +4900 REM ==DRAW NOSE== +4920 HCOLOR=0: +4940 IF (FILL=1) THEN 4980 +4960 HCOLOR=3 +4980 HPLOT 146,48 TO 143,52 TO 146,52 +5000 RETURN +5020 : +5040 : +5100 REM ==DRAW MOUTH== +5120 HCOLOR=5: HPLOT 140,60 TO 143,56 TO 149,56 TO 152,60 +5140 RETURN +5160 : +5180 : +5200 REM ==DRAW SMILEY MOUTH== +5220 IF GG=0 THEN 5440 +5240 HCOLOR=0: HPLOT 140,60 TO 143,56 TO 149,56 TO 152,60 +5260 HCOLOR=0 +5280 HPLOT 146,70 TO 146,106:HPLOT 146,88 TO 116,58:HPLOT 146,88 TO 176,58 +5300 HPLOT 146,106 TO 116,140:HPLOT 146,106 TO 176,140 +5320 GOSUB 3880 +5340 IF (NLIMBS < 1) THEN GOSUB 4380 +5360 IF (NLIMBS < 2) THEN GOSUB 4500 +5380 IF (NLIMBS < 3) THEN GOSUB 4700 +5400 IF (NLIMBS < 4) THEN GOSUB 4900 +5420 HCOLOR=5: HPLOT 138,60 TO 143,64 TO 149,64 TO 154,60 +5440 RETURN +5460 : +5480 : +5500 REM ==DRAW TORSO== +5520 HCOLOR=2: HPLOT 146,70 TO 146,106 +5540 RETURN +5560 : +5580 : +5600 REM ==DRAW LEFT ARM== +5620 HPLOT 146,88 TO 116,58 +5640 RETURN +5660 : +5680 : +5700 REM ==DRAW RIGHT ARM== +5720 HPLOT 146,88 TO 176,58 +5740 RETURN +5760 : +5780 : +5800 REM ==DRAW LEFT LEG== +5820 HPLOT 146,106 TO 116,140 +5840 RETURN +5860 : +5880 : +5900 REM ==DRAW RIGHT LEG== +5920 HPLOT 146,106 TO 176,140 +5940 RETURN +5960 : +5980 : +6000 REM *** SUBROUTINE: CIRCLE2 +6020 REM * IN: RADIUS +6040 REM * IN: CX (X COORDINATE OF CENTER) +6060 REM * IN: CY (Y COORDINATE OF CENTER) +6080 REM * IN: FILL (0 OR 1) +6100 REM *** +6120 PI = ATN (1) * 4: REM = 3.14159265 +6140 I0 = PI / 2:I1 = 0:DI = PI / (RADIUS * 4) +6160 I1 = I1 - 0.1: REM SLOP TO FILL IN LAST LINE +6180 I = I0 +6200 IF (I < = I1) THEN 7360 +6220 X0 = - 666:X1 = - 666:Y0 = - 666 +6300 REM +6320 DX = COS (I) * RADIUS:X = INT (0.5 + CX - DX) +6340 DY = SIN (I) * RADIUS:Y = INT (0.5 + CY - DY) +6400 REM PRINT "X = ";X;", Y = ";Y +6420 IF (X0 = - 666) THEN 6500 +6440 IF (Y0 < > Y) THEN 6600 +6460 X1 = X +6480 GOTO 7300 +6500 REM FIRST POINT IN NEW LINE +6520 X0 = X:X1 = X:Y0 = Y: GOTO 7300 +6600 REM END OF LINE +6620 IF X0 < = - 666 THEN 7200 +6640 R0X = CX + (CX - X0) +6660 IF R0X < GW THEN 6700 +6680 R0X = GW - 1 +6700 R1X = CX + (CX - X1) +6720 IF R1X < GW THEN 6760 +6740 R1X = GW - 1 +6760 IF X0 > = 0 THEN 6800 +6780 X0 = 0 +6800 IF X1 > = 0 THEN 6840 +6820 X1 = 0 +6840 Y2 = CY + (CY - Y0) +6900 REM DRAW THE LINE(S) +6920 REM PRINT "HPLOT ";X0;",";Y0;" TO ";R0X;",";Y0 +6940 REM GET A$:IF (A$ = "Q") THEN END +6960 IF (Y0 < 0) OR (Y0 > = GH) THEN 7040: REM LINE NOT ON SCREEN +6980 IF FILL = 0 THEN 7020 +7000 HPLOT X1,Y0 TO R1X,Y0: GOTO 7040 +7020 HPLOT X1,Y0 TO X0,Y0: HPLOT R0X,Y0 TO R1X,Y0 +7040 IF (Y2 < 0) OR (Y2 > = GH) THEN 7120 +7060 IF FILL = 0 THEN 7100 +7080 HPLOT X1,Y2 TO R1X,Y2: GOTO 7120 +7100 HPLOT X1,Y2 TO X0,Y2: HPLOT R0X,Y2 TO R1X,Y2 +7120 Y0 = Y0 + 1:Y2 = Y2 - 1 +7140 IF Y0 < = Y THEN 6960 +7200 REM END OF DRAWING LINE +7220 I = I - DI +7240 GOTO 6200 +7300 REM END OF RADIAN, PREPARE NEXT +7320 I = I - DI +7340 IF (I > I1) THEN 6300 +7360 RETURN +7400 REM ==DISPLAY STATUS== +7420 REM HOME +7440 IF CHEET = 0 THEN 7520 +7460 VTAB 21: HTAB 1: CALL -868: PRINT "* Pssst... the word is ";SECRET$;"." +7480 D = 2: GOSUB 800 +7500 CHEET=0 +7520 I = SW / 2 - LEN (HIDDEN$) / 2 +7540 IF I < 1 THEN 7580 +7560 VTAB 22: HTAB I +7580 PRINT HIDDEN$ +7600 RETURN +7620 : +7640 : +7700 REM ==GET A GUESS== +7720 OGUESS$ = "" +7740 FOR I = 0 TO 25 +7760 IF (GZ%(I) > 0) THEN 7820 +7780 OGUESS$ = OGUESS$ + CHR$ ( ASC ("A") + I) +7800 GOTO 7840 +7820 OGUESS$ = OGUESS$ + "." +7840 NEXT I +7860 VTAB 23: CALL - 868 +7880 VTAB 24: HTAB 1: PRINT "Guess? (";OGUESS$;") "; +7900 GOSUB 1800:GUESS$ = A$ +7920 IF (GZ%( ASC (A$) - ASC ("A")) = 0) THEN 7980 +7940 GOSUB 14300: REM RING BELL ON DUPE GUESS +7960 GOTO 7880 +7980 GZ%( ASC (A$) - ASC ("A")) = 1 +8000 HTAB 1: CALL - 868 +8020 L=ASC(A$) - ASC("A") + 1:FOR I=1 TO L:D=RND(1):NEXT I:REM TWEAK RANDOM +8025 RETURN +8040 : +8060 : +8100 REM ==CHECK GUESS== +8120 OK = 0:DUP = 0:TK = 0:NHIDDEN$ = "" +8140 FOR I = 1 TO LEN (SECRET$) +8160 IF I = 1 THEN 8200 +8180 NHIDDEN$ = NHIDDEN$ + " " +8200 A$ = MID$ (HIDDEN$,2 * I - 1,1) +8220 IF (A$ = "_") THEN 8260 +8240 TK = TK + 1 +8260 IF ( MID$ (SECRET$,I,1) < > GUESS$) THEN 8340 +8280 IF (A$ = GUESS$) THEN DUP = 1 +8300 A$ = GUESS$ +8320 OK = OK + 1 +8340 NHIDDEN$ = NHIDDEN$ + A$ +8360 NEXT I +8380 IF (DUP = 1) THEN 8900 +8400 IF (OK = 0) THEN 9000 +8420 TK = TK + OK +8440 IF TK = LEN (SECRET$) THEN 9400 +8500 REM CORRECT GUESS +8520 IF (SND > 0) THEN POKE 768,32: POKE 769,12: CALL 770 +8540 RARE$ = "QZXJ":FRARE = 0 +8560 FOR I = 1 TO LEN (RARE$) +8580 IF ( MID$ (RARE$,I,1) = GUESS$) THEN FRARE = 1 +8600 NEXT I +8620 IF FRARE = 0 THEN 8660 +8640 PRINT "Glorious!!!";: GOTO 8780 +8660 I = INT ( RND (1) * 3) + 1 +8680 ON I GOTO 8720,8740,8760 +8700 PRINT "Whaa? This wasn't supposed to happen.";: GOTO 8780 +8720 PRINT "Bah! Lucky guess.";: GOTO 8780 +8740 PRINT "Nice work!";: GOTO 8780 +8760 PRINT "Good job!";: GOTO 8780 +8780 HIDDEN$ = NHIDDEN$ +8800 D=2: GOSUB 800:HTAB 1: CALL -868:GOTO 9520 +8900 REM DUPLICATE GUESS +8920 PRINT "You already guessed '";GUESS$;"'."; +8940 GOTO 9520 +9000 REM WRONG GUESS +9020 I=20: GOSUB 14200: REM BZZZ +9040 PRINT "Wrong! The secret word has no '";GUESS$;"'."; +9060 NLIMBS = NLIMBS + 1 +9080 GOSUB 4100: REM SHOW NEWLY ADDED LIMB ON THE GALLOWS +9100 IF (LIMBS$(NLIMBS + 1) = "***HANGMAN***") THEN 9200 +9120 D=1: GOSUB 800:CALL -868:GOTO 9520 +9200 REM YOU LOSE +9220 GAMEOVER = 1 +9240 PRINT : HTAB 1: CALL -868: PRINT "You lose. The secret word was... " +9260 HTAB 1: CALL -868: PRINT " ";SECRET$;"." +9280 A$ = "48 ,27 ,57 ,54 ,72 ,54 ,114,255.": GOSUB 14000 +9300 GOTO 9520 +9400 REM YOU WIN +9420 HTAB 1: CALL -868: PRINT "You WIN! You solved the secret word, " +9440 HTAB 1: CALL -868: PRINT " ";SECRET$;"." +9460 A$ = "128,27 ,114,54 ,114,54 ,85 ,216.": GOSUB 14000 +9480 GAMEOVER = 1 +9500 GOSUB 5200 +9520 RETURN +9540 : +9560 : +9600 REM ==SELECT WORD== +9620 HOME:VTAB 24:PRINT "Choosing word, please wait..."; +9640 NR = 0 +9660 NR = NR + 1: IF (NR > 100) THEN ES$ = "COULD NOT LOAD A VALID WORD": GOTO 1620 +9680 IF NW < = 0 THEN ES$ = "NO WORDS LOADED": GOTO 1620 +9700 RESTORE +9720 WI = INT ( RND (1) * NW) + 1 +9740 IF WI = WO THEN 9720: REM DON'T PICK SAME WORD +9760 FOR I = 1 TO WI +9780 READ SECRET$ +9800 NEXT I +9820 OK = 0:AA = ASC ("A"):AZ = ASC ("Z") +9840 FOR I = 1 TO LEN (SECRET$) +9860 C = ASC ( MID$ (SECRET$,I,1)) +9880 IF (C < AA) OR (C > AZ) THEN 9920 +9900 OK = OK + 1 +9920 NEXT I +9940 IF ( LEN (SECRET$) < 3) OR ( LEN (SECRET$) > 20) THEN OK = 0: GOTO 10200 +10000 REM IF (EZ = 1) AND ( LEN (SECRET$) > 5) THEN OK = 0: GOTO 10200 +10020 A$ = SECRET$: GOSUB 12100: REM SET WD=WORD DIFFICULTY +10100 REM HTAB 1:PRINT "___ ";SECRET$;" = ";WD +10120 IF (EZ = 1) AND (WD > 0.36) THEN OK = 0 +10140 IF (EZ = 2) AND ((WD < = 0.36) OR (WD > 0.66)) THEN OK = 0 +10160 IF (EZ = 3) AND (WD < = 0.66) THEN OK = 0 +10180 IF (OK > 0) THEN 10320 +10200 REM ==WORD NOT OK, PICK ANOTHER== +10220 WI = WI + 1 +10240 IF (WI > NW) THEN GOTO 9660 +10260 NR = NR + 1: IF (NR > 100) THEN ES$ = "COULD NOT LOAD A VALID WORD": GOTO 1620 +10280 READ SECRET$ +10300 GOTO 9820 +10320 WO = WI +10400 REM SECRET$="TYRANNOSAURUS REX" : REM FOR TESTING +10420 HIDDEN$ = "" +10440 FOR I = 1 TO LEN (SECRET$) +10460 IF I = 1 THEN 10500 +10480 HIDDEN$ = HIDDEN$ + " " +10500 C = ASC ( MID$ (SECRET$,I,1)) +10520 IF (C < AA) OR (C > AZ) THEN 10560 +10540 HIDDEN$ = HIDDEN$ + "_": GOTO 10580 +10560 HIDDEN$ = HIDDEN$ + MID$ (SECRET$,I,1) +10580 NEXT I +10600 HTAB 1: CALL - 868: REM ERASE STATUS MESSAGE +10620 RETURN +10640 : +10660 : +10700 REM ==COUNT AVAILABLE WORDS== +10720 REM THE ARRAYS BELOW ARE USED TO CALCULATE LETTER FREQUENCIES, WHICH IN +10740 REM TURN ARE USED TO CATEGORIZE WORDS INTO EASY, MEDIUM, AND HARD LEVELS. +10760 REM THE FQ TABLE IS INITIALIZED TO THE FREQUENCIES CORRESPONDING TO +10780 REM OVERALL ENGLISH LANGUAGE USAGE. IF CQ<>0, THEN WE OVERWRITE THESE +10800 REM WITH THE FREQS DETERMINED FROM THE WORD LIST ITSELF, WHICH IS MORE +10820 REM MORE ACCURATE BUT TAKES A LOT OF TIME TO DO AT STARTUP. +10840 DIM FQ(27),FC(27) +10860 FQ(0) = 8.167: REM "A" +10880 FQ(1) = 1.492 +10900 FQ(2) = 2.782 +10920 FQ(3) = 4.253 +10940 FQ(4) = 12.702 +10960 FQ(5) = 2.228 +10980 FQ(6) = 2.015 +11000 FQ(7) = 6.094 +11020 FQ(8) = 6.966 +11040 FQ(9) = 0.153 +11060 FQ(10) = 0.772 +11080 FQ(11) = 4.025 +11100 FQ(12) = 2.406 +11120 FQ(13) = 6.749 +11140 FQ(14) = 7.507 +11160 FQ(15) = 1.929 +11180 FQ(16) = 0.095 +11200 FQ(17) = 5.987 +11220 FQ(18) = 6.327 +11240 FQ(19) = 9.056 +11260 FQ(20) = 2.758 +11280 FQ(21) = 0.978 +11300 FQ(22) = 2.360 +11320 FQ(23) = 0.150 +11340 FQ(24) = 1.974 +11360 FQ(25) = 0.074: REM "Z" +11380 CQ = 0 +11400 FOR I = 0 TO 26:FC(I) = 0: NEXT I +11420 RESTORE :NW = 0:NB = 0 +11440 READ SECRET$ +11460 IF SECRET$ = "*NO MORE WORDS*" THEN 11700 +11480 IF (CQ = 0) THEN 11620 +11500 L = LEN (SECRET$):AA = ASC ("A"):AZ = ASC ("Z") +11520 FOR I = 1 TO L +11540 C = ASC ( MID$ (SECRET$,I,1)) +11560 IF (C < AA) OR (C > AZ) THEN 11600 +11580 C = C - AA:FC(C) = FC(C) + 1 +11600 NEXT I +11620 NW = NW + 1 +11640 IF NW > 10000 THEN ES$ = "INVALID WORD DATA": GOTO 1620 +11660 IF ( LEN (SECRET$) < 3) OR ( LEN (SECRET$) > 20) THEN NB = NB + 1 +11680 GOTO 11440 +11700 IF (NW < 1) OR (NB > = NW) THEN ES$ = "INVALID WORD DATA": GOTO 1620 +11800 REM COMPUTE ALPHABET FREQUENCIES +11820 FOR I = 0 TO 25:FC(26) = FC(26) + FC(I): NEXT I +11840 IF CQ = 0 THEN 11900 +11860 FOR I = 0 TO 25:FQ(I) = FC(I) * 100 / FC(26): NEXT I +11900 REM GOSUB 12600 +11920 REM GOSUB 12800 +11940 REM A$="YAK": GOSUB 12100 +11960 RETURN +11980 : +12000 : +12100 REM ==CALCULATE WORD DIFFICULTY== +12120 IF (FQ(0) < = 0) THEN 12440 +12140 WD = 0:AA = ASC ("A"):AZ = ASC ("Z") +12160 L = LEN (A$) +12180 FOR I = 1 TO L +12200 C = ASC ( MID$ (A$,I,1)) +12220 IF (C < AA) OR (C > AZ) THEN 12280 +12240 QC = FQ(C - AA) +12260 WD = WD + 1 / (QC * QC) +12280 NEXT I +12300 IF (WD < = 0) OR (L < = 0) THEN 12440 +12400 REM WD = WD / L +12420 GOTO 12500 +12440 WD = 0 +12500 REM HTAB 1:PRINT:PRINT "DIFFICULTY FOR ";A$;" = ";WD;".":PRINT +12520 RETURN +12540 : +12560 : +12600 REM ==PRINT FREQUENCIES== +12620 HTAB 1: PRINT : PRINT +12640 AA = ASC ("A") +12660 FOR I = 1 TO 13 +12680 PRINT CHR$ (AA + I - 1);": ";FQ(I - 1);" "; CHR$ (AA + I - 1 + 13);": ";FQ(I - 1 + 13) +12700 NEXT I +12720 PRINT : INPUT "PRESS RETURN TO CONTINUE...";A$ +12740 RETURN +12760 : +12780 : +12800 REM ==CALCULATE AVERAGE WORD DIFFICULTY== +12820 RESTORE +12840 NW = 0:TD = 0:D0 = 999999:D9 = - 1:W0$ = "":W9$ = "" +12860 READ SECRET$ +12880 IF SECRET$ = "*NO MORE WORDS*" THEN 13000 +12900 A$ = SECRET$: GOSUB 12100 +12920 NW = NW + 1:TD = TD + WD +12940 IF WD < D0 THEN D0 = WD:W0$ = A$ +12960 IF WD > D9 THEN D9 = WD:W9$ = A$ +12980 GOTO 12860 +13000 IF NW < = 0 THEN 13140 +13020 TD = TD / NW +13040 HTAB 1: PRINT : PRINT +13060 PRINT "AVG DIFFICULTY = ";TD +13080 PRINT "EASIEST WORD = ";D0;", ";W0$ +13100 PRINT "HARDEST WORD = ";D9;", ";W9$ +13120 PRINT : INPUT "PRESS RETURN TO CONTINUE...";A$ +13140 RETURN +13160 : +13180 : +13200 REM ================== +13220 REM DATA SECTION: +13240 REM SECRET WORDS ARE +13260 REM LISTED BELOW. +13280 REM ================== +13300 NW = 0: REM NUMBER OF WORDS LOADED +13320 SECRET$ = "" +13340 WI = - 1: REM SECRET WORD # +13360 WO = - 1: REM PREVIOUS SECRET WORD # +13380 DATA ALLIGATOR,ANT,APE,BAT,BEAR,BEE,BIRD,BOBCAT,CAT,CENTIPEDE,CHEETAH,CHICKEN,CHIMPANZEE,CLAM,COBRA +13400 DATA CONDOR,COUGAR,COW,CROCODILE,DEER,DINGO,DOG,DONKEY,DUCK,EAGLE,ELECTRIC EEL,ELEPHANT,ELK,EMU,FISH,FOX,FROG,GAZELLE +13420 DATA GIRAFFE,GOAT,GOOSE,GORILLA,GRIZZLY BEAR,HAWK,HEDGEHOG,HIPPOPOTAMUS,HORSE,HYENA,IGUANA,JAGUAR +13440 DATA JELLYFISH,KANGAROO,KRILL,LEMUR,LEOPARD,LION,LIZARD,LLAMA,LOBSTER,LYNX,MOLE,MONKEY,MOOSE,NEWT +13460 DATA OCTOPUS,OKAPI,OPOSSUM,ORANGUTAN,OTTER,OWL,PANDA,PENGUIN,PIG,POLAR BEAR,PORCUPINE,PUMA,QUAIL +13480 DATA RABBIT,RACCOON,REINDEER,RHINOCEROS,SCORPION,SEA LION,SEAL,SHARK,SHRIMP,SNAIL,SNAKE,SPIDER,SQUID +13500 DATA SQUIRREL,TIGER,TOAD,TORTOISE,TUNA,TURKEY,TURTLE,TYRANNOSAURUS REX,VOLE,VULTURE,WALRUS,WARTHOG,WASP,WHALE,WILDCAT,WILDEBEEST +13520 DATA WOLF,WORM,YAK,ZEBRA +13540 DATA "*NO MORE WORDS*" +13600 REM THIS VERSION OF THE PROGRAM +13620 REM HAS DATA BUILT-IN, RATHER +13640 REM THAN USING A DATAFILE. +13660 GOSUB 10700 +13680 RETURN +13700 : +13720 : +13800 REM ==INSTALL TONE GENERATOR== +13820 IF (SND = 0) THEN 13880 +13840 POKE 770, 173: POKE 771, 48: POKE 772, 192: POKE 773, 136: POKE 774, 208: POKE 775, 5: POKE 776, 206: POKE 777, 1: POKE 778, 3: POKE 779, 240 +13860 POKE 780, 9: POKE 781, 202: POKE 782, 208: POKE 783, 245: POKE 784, 174: POKE 785, 0: POKE 786, 3: POKE 787, 76: POKE 788, 2: POKE 789, 3: POKE 790, 96 +13880 RETURN +13900 : +13920 : +14000 REM ==PLAY TUNE== +14020 REM A$ = "128,27 ,114,54 ,114,54 ,85 ,216." +14040 IF (SND = 0) THEN 14140 +14060 L=LEN(A$) +14080 I=1 +14100 IF (I+7 > L) THEN 14140 +14120 POKE 768,VAL(MID$(A$,I,3)): POKE 769,VAL(MID$(A$,I+4,3)): CALL 770: I = I + 8: GOTO 14100 +14140 RETURN +14160 : +14180 : +14200 REM ==BUZZ SPEAKER== +14220 L=PEEK(-16336):I=I-1:IF (I > 0) THEN 14220 +14240 RETURN +14260 : +14280 : +14300 REM ==RING BELL== +14320 IF (SND = 0) THEN 14360 +14340 CALL -198: REM COULD ALSO JUST PRINT CHR$(7) +14360 RETURN diff --git a/samples/sample.hellosine.txt b/samples/sample.hellosine.txt new file mode 100644 index 0000000..1e525f3 --- /dev/null +++ b/samples/sample.hellosine.txt @@ -0,0 +1,6 @@ +0 PR#3 +5 x = 0 +7 sp = int(30 + (30* sin(x* 3.14159 / 180 ) )) +10 PRINT spc(sp);"Hello World" +20 x = x + 15 +30 goto 7 diff --git a/samples/sample.hireswalk.txt b/samples/sample.hireswalk.txt new file mode 100644 index 0000000..fa7d28d --- /dev/null +++ b/samples/sample.hireswalk.txt @@ -0,0 +1,34 @@ +10 HGR +20 X=140: Y=80 +30 C=INT(RND(1)*8) +40 BR=3 +40 HCOLOR=C: HPLOT X,Y: HPLOT X-1,Y-1: HPLOT X+1,Y+1 +50 HPLOT X+1,Y-1: HPLOT X-1,Y+1 +60 HPLOT X+1,Y: HPLOT X-1,Y: HPLOT X,Y+1: HPLOT X,Y-1 +70 IF RND(1)>=.9 THEN C=INT(RND(1)*8) +80 IF RND(1)>=.9 THEN BR=BR + INT(RND(1)*3) - 1 +90 IF BR<1 THEN BR=1 +100 IF BR>7 THEN BR=7 +110 NX = X + INT(RND(1)*15) - 7 +120 NY = Y + INT(RND(1)*15) - 7 +130 IF NX > 279 THEN NX=279 +140 IF NX < 0 THEN NX=0 +150 IF NY > 159 THEN NY=159 +160 IF NY < 0 THEN NY=0 +170 HCOLOR=C +180 FOR I=-INT(BR/2) TO INT((BR+1)/2) +190 FOR J=-INT(BR/2) TO INT((BR+1)/2) +200 X1=X+I: X2=NX+I: Y1=Y+J: Y2=NY+J +210 IF X1>279 THEN X1=279 +220 IF X1<0 THEN X1=0 +230 IF X2>279 THEN X2=279 +240 IF X2<0 THEN X2=0 +250 IF Y1>159 THEN Y1=159 +260 IF Y1<0 THEN Y1=0 +270 IF Y2>159 THEN Y2=159 +280 IF Y2<0 THEN Y2=0 +290 HPLOT X1,Y1 TO X2,Y2 +300 NEXT: NEXT +310 X=NX: Y=NY +320 GOTO 70 + diff --git a/samples/sample.jot.txt b/samples/sample.jot.txt new file mode 100644 index 0000000..7ed22fb --- /dev/null +++ b/samples/sample.jot.txt @@ -0,0 +1,168 @@ +1 TEXT : HOME : PRINT "THIS GAME IS PLAYED ENTIRELY WITH" +2 FLASH : PRINT "3";: NORMAL : PRINT "-LETTER WORDS. ALL LETTERS IN A WORD" +3 PRINT "MUST BE UNIQUE (FOR EXAMPLE, 'POP' IS" +4 PRINT "*NOT* A VALID WORD).": PRINT +5 PRINT "TO BEGIN THE GAME, BOTH YOU AND I WILL" +6 PRINT "CHOOSE A SECRET WORD. THE FIRST PLAYER" +7 PRINT "TO GUESS THE OTHER'S WORD WINS.": PRINT +8 PRINT "AFTER EACH GUESS, THE ASKER IS TOLD" +9 PRINT "HOW MANY LETTERS WERE CORRECT. THE" +10 PRINT "POSITION OF THE LETTERS DOES *NOT*" +11 PRINT "MATTER (FOR EXAMPLE, IF THE WORD WAS" +12 PRINT "'OWN' A GUESS OF 'WHO' WOULD HAVE 2" +13 PRINT "HITS.": PRINT +95 INPUT "READY? ";Q$ +99 M1 = 0:M2 = 0 +100 REM : JOT +110 REM : COPYRIGHT 1980 BY PHIL FELDMAN AND TOM RUGG +150 M = 25:N = 406 +160 DIM A$(N) +170 DIM G1$(M),G2$(M),H1(M),H2(M) +200 G1 = 0:G2 = 0 +210 L = N:Q = PEEK (78) + 256 * PEEK (79):Q = RND ( - Q) +250 TEXT : HOME : PRINT TAB(17);"J O T": PRINT +260 PRINT "JUST A MOMENT PLEASE .....": GOSUB 3000:Q = INT(RND (1) * N) + 1: PRINT +270 PRINT "THANKS, NOW LET'S EACH THINK": PRINT "OF OUR SECRET WORD" +280 PRINT : PRINT "(THIS TAKES ME A WHILE ...)" +290 GOSUB 2200:M$ = A$(Q): PRINT : PRINT "OK, "; +300 INPUT "DO YOU WANT TO GO FIRST? ";Q$ +310 Q$ = LEFT$ (Q$,1): IF Q$ = "N" THEN 600 +320 IF Q$ = "Y" THEN 500 +330 PRINT : PRINT "YES OR NO PLEASE": PRINT : GOTO 300 +500 M2 = M2 + 1: IF M2 = 1 THEN PRINT : PRINT "TYPE S FOR LIST OF PREVIOUS GUESSES." +502 PRINT : INPUT "YOUR GUESS (OR S)? ";P$: IF P$ = "S" THEN GOSUB 1000: GOTO 500 +510 IF P$ = "Q" THEN 1200 +520 IF P$ = M$ THEN G1 = G1 + 1:G1$(G1) = P$:H1(G1) = 9: GOTO 3400 +530 GOSUB 1800: IF F = 0 THEN PRINT "THAT'S NOT A LEGAL WORD -- TRY AGAIN": GOTO 500 +540 Q$ = M$: GOSUB 2600:Q$ = P$: GOSUB 1500 +550 PRINT "# OF HITS IS ";Q +560 G1 = G1 + 1:G1$(G1) = Q$:H1(G1) = Q +570 IF G1 = M THEN 3600 +600 Q$ = A$(L):G2 = G2 + 1:G2$(G2) = Q$ +610 PRINT : PRINT "MY GUESS IS -- ";Q$ +615 M1 = M1 + 1: IF M1 = 1 THEN PRINT : PRINT "IF I AM RIGHT, TYPE R." +620 INPUT "HOW DID I DO (0-3 OR R)? ";P$ +630 P$ = LEFT$ (P$,1) +640 IF P$ = "R" THEN H2(G2) = 9: GOTO 3200 +650 P = VAL (P$): IF P > 3 OR (P = 0 AND P$ < > "0") THEN PRINT "BAD ANSWER": GOTO 610 +660 IF L > 100 THEN PRINT : PRINT "I'M THINKING ..." +670 H2(G2) = P: GOSUB 800 +680 GOTO 500 +800 Q$ = G2$(G2):H = H2(G2):J = 0: GOSUB 2600:L = L - 1: IF L < 1 THEN 900 +810 J = J + 1: IF J > L THEN 870 +820 Q$ = A$(J): GOSUB 1500 +830 IF Q = H THEN 810 +840 A = J:B = L: GOSUB 2400:L = L - 1 +850 IF L < 1 THEN 900 +860 IF L > = J THEN 820 +870 RETURN +900 PRINT : PRINT "SOMETHING'S WRONG !!" +910 PRINT : INPUT "WHAT'S YOUR SECRET WORD? ";P$: GOSUB 1800 +920 IF F = 0 THEN PRINT : PRINT "ILLEGAL WORD -- I NEVER HAD A CHANCE": GOTO 1200 +930 PRINT : PRINT "YOU GAVE A BAD ANSWER SOMEWHERE --" +940 PRINT "CHECK THE SUMMARY": GOSUB 1000 +950 GOTO 1200 +1000 PRINT :Q = G1: IF G2 > G1 THEN Q = G2 +1010 IF Q = 0 THEN PRINT "NO GUESSES YET": RETURN +1020 PRINT TAB(1);: FOR J = 1 TO 37: PRINT "-";: NEXT : PRINT "-" +1030 PRINT TAB(1);: INVERSE : PRINT "YOUR GUESSES";: NORMAL +1040 PRINT " SUMMARY ";: INVERSE +1050 PRINT "MY GUESSES";: NORMAL : PRINT " " +1060 PRINT "WORD HITS"; TAB(29);"WORD HITS" +1070 FOR J = 1 TO Q:K = 1: IF J > 9 THEN K = 0 +1080 IF J > G1 THEN PRINT TAB(19 + K);J; TAB(30);G2$(J); TAB(36);H2(J): GOTO 1110 +1090 IF J > G2 THEN PRINT TAB(2);G1$(J); TAB(9);H1(J); TAB(19 + K);J: GOTO 1110 +1100 PRINT TAB(2);G1$(J); TAB(9);H1(J); TAB(19 + K);J; TAB(30);G2$(J); TAB(36);H2(J) +1110 NEXT : RETURN +1200 PRINT : INPUT "HOW ABOUT ANOTHER GAME? ";Q$ +1210 Q$ = LEFT$ (Q$,1): IF Q$ = "Y" THEN 200 +1220 IF Q$ = "N" THEN END +1230 PRINT : PRINT "YES OR NO PLEASE": GOTO 1200 +1500 P$ = LEFT$ (Q$,1):Q = 0: GOSUB 1600 +1510 P$ = MID$ (Q$,2,1): GOSUB 1600 +1520 P$ = RIGHT$ (Q$,1): GOSUB 1600: RETURN +1600 IF P$ = M1$ OR P$ = M2$ OR P$ = M3$ THEN Q = Q + 1 +1610 RETURN +1800 F = 0 +1810 FOR J = 1 TO N +1820 IF A$(J) = P$ THEN F = 1: RETURN +1830 NEXT : RETURN +2200 FOR A = N TO 100 STEP - 1:B = INT ( RND (1) * A) + 1 +2210 GOSUB 2400: NEXT +2220 PRINT : PRINT "I'VE ALMOST GOT IT ..." +2230 FOR A = 99 TO 2 STEP - 1:B = INT ( RND (1) * A) + 1 +2240 GOSUB 2400: NEXT : RETURN +2400 Q$ = A$(B):A$(B) = A$(A):A$(A) = Q$: RETURN +2600 M1$ = LEFT$ (Q$,1):M2$ = MID$ (Q$,2,1) +2610 M3$ = RIGHT$ (Q$,1): RETURN +3000 RESTORE : FOR P = 1 TO N: READ A$(P): NEXT : RETURN +3200 PRINT : PRINT "IT SURE FEELS GOOD" +3210 PRINT : PRINT "MY WORD WAS -- ";M$ +3220 GOTO 1200 +3400 PRINT : PRINT "CONGRATULATIONS - THAT WAS IT": PRINT +3410 INPUT "WHAT WAS YOUR WORD? ";P$: GOSUB 1800:J = 1 +3420 IF F = 0 THEN PRINT : PRINT "ILLEGAL WORD - I HAD NO CHANCE": GOTO 1200 +3430 IF A$(J) = P$ THEN PRINT : PRINT "NICE WORD": GOTO 1200 +3440 J = J + 1: IF J < = L THEN 3430 +3450 PRINT : PRINT "YOU MADE AN ERROR SOMEWHERE": PRINT "-- CHECK THE SUMMARY" +3460 GOSUB 1000: GOTO 1200 +3600 PRINT : PRINT "SORRY, I'M OUT OF MEMORY": PRINT +3610 PRINT "MY WORD WAS - ";M$: GOTO 1200 +5000 DATA ACE,ACT,ADE,ADO,ADS,AFT,AGE +5010 DATA AGO,AID,AIL,AIM,AIR,ALE,ALP +5020 DATA AND,ANT,ANY,APE,APT,ARC,ARE +5030 DATA ARK,ARM,ART,ASH,ASK,ASP,ATE +5040 DATA AWE,AWL,AXE,AYE,BAD,BAG,BAN +5050 DATA BAR,BAT,BAY,BED,BEG,BET,BID +5060 DATA BIG,BIN,BIT,BOA,BOG,BOW,BOX +5070 DATA BOY,BUD,BUG,BUM,BUN,BUS,BUT +5080 DATA BUY,BYE,CAB,CAD,CAM,CAN,CAP +5090 DATA CAR,CAT,COB,COD,COG,CON,COP +5100 DATA COT,COW,COY,CRY,CUB,CUD,CUE +5110 DATA CUP,CUR,CUT,DAB,DAM,DAY,DEN +5120 DATA DEW,DIE,DIG,DIM,DIN,DIP,DOE +5130 DATA DOG,DON,DOT,DRY,DUB,DUE,DUG +5140 DATA DYE,DUO,EAR,EAT,EGO,ELK,ELM +5150 DATA END,ELF,ERA,FAD,FAG,FAN,FAR +5160 DATA FAT,FED,FEW,FIG,FIN,FIR,FIT +5170 DATA FIX,FLY,FOE,FOG,FOR,FOX,FRY +5180 DATA FUN,FUR,GAP,GAS,GAY,GEM,GET +5190 DATA GIN,GNU,GOB,GOD,GOT,GUM,GUN +5200 DATA GUT,GUY,GYP,HAD,HAG,HAM,HAS +5210 DATA HAT,HAY,HEN,HEX,HID,HIM,HIP +5220 DATA HIS,HIT,HER,HEM,HOE,HOG,HOP +5230 DATA HOT,HOW,HUB,HUE,HUG,HUM,HUT +5240 DATA ICE,ICY,ILK,INK,IMP,ION,IRE +5250 DATA IRK,ITS,IVY,JAB,JAR,JAW,JAY +5260 DATA JOB,JOG,JOT,JOY,JUG,JAG,JAM +5270 DATA JET,JIB,JIG,JUT,KEG,KEY,KID +5280 DATA KIN,KIT,LAB,LAD,LAG,LAP,LAW +5290 DATA LAY,LAX,LED,LEG,LET,LID,LIE +5300 DATA LIP,LIT,LOB,LOG,LOP,LOT,LOW +5310 DATA LYE,MAD,MAN,MAP,MAR,MAT,MAY +5320 DATA MEN,MET,MID,MOB,MOP,MOW,MUD +5330 DATA MIX,MUG,NAB,NAG,NAP,NAY,NET +5340 DATA NEW,NIL,NIP,NOD,NOT,NOR,NOW +5350 DATA NUT,OAF,OAK,OAR,OAT,ODE,OIL +5360 DATA OLD,ONE,OPT,ORE,OUR,OUT,OVA +5370 DATA OWE,OWL,OWN,PAD,PAL,PAN,PAR +5380 DATA PAT,PAW,PAY,PEA,PEG,PEN,PET +5390 DATA PEW,PIE,PIG,PIT,PLY,POD,POT +5400 DATA POX,PER,PIN,PRO,PRY,PUB,PUN +5410 DATA PUS,PUT,RAG,RAM,RAN,RAP,RAT +5420 DATA RAW,RAY,RED,RIB,RID,REV,RIG +5430 DATA RIM,RIP,ROB,ROD,ROE,ROT,ROW +5440 DATA RUB,RUE,RUG,RUM,RUN,RUT,RYE +5450 DATA SAD,SAG,SAP,SAT,SAW,SAY,SET +5460 DATA SEW,SEX,SHY,SEA,SIN,SHE,SIP +5470 DATA SIR,SIT,SIX,SKI,SKY,SLY,SOB +5480 DATA SOD,SON,SOW,SOY,SPA,SPY,STY +5490 DATA SUE,SUM,SUN,TAB,TAD,TAG,TAN +5500 DATA TAP,TAX,TAR,TEA,TEN,THE,THY +5510 DATA TIC,TIE,TIN,TIP,TOE,TON,TOP +5520 DATA TOW,TOY,TRY,TUB,TUG,TWO,URN +5530 DATA USE,UPS,VAN,VAT,VEX,VIA,VIE +5540 DATA VIM,VOW,YAK,YAM,YEN,YES,YET +5550 DATA YOU,WAD,WAG,WAN,WAR,WAS,WAX +5560 DATA WAY,WEB,WED,WET,WHO,WHY,WIG +5570 DATA WIN,WIT,WOE,WON,WRY,ZIP,FIB \ No newline at end of file diff --git a/samples/sample.keyboard.txt b/samples/sample.keyboard.txt new file mode 100644 index 0000000..a842a28 --- /dev/null +++ b/samples/sample.keyboard.txt @@ -0,0 +1,9 @@ +0 text : home : pr#0 +1 c = peek(49152) : poke 49168,0 +: htab 1 : vtab 20 : normal +2 if c >= 128 then c = c - 128 : inverse +4 y = int(c/16) : x = c - y * 16 +: htab x * 2 + 1 : vtab y + 1 +5 if c >= 32 then print chr$(c); +6 if c < 32 then print chr$(127); +9 goto 1 diff --git a/samples/sample.loreswalk.txt b/samples/sample.loreswalk.txt new file mode 100644 index 0000000..3649427 --- /dev/null +++ b/samples/sample.loreswalk.txt @@ -0,0 +1,12 @@ +10 GR +20 X=20: Y=20 +30 C=INT(RND(1)*16) +40 COLOR=C: PLOT X,Y +50 IF RND(1)>=.9 THEN C=INT(RND(1)*16) +60 X = X + INT(RND(1)*3) - 1 +70 Y = Y + INT(RND(1)*3) - 1 +80 IF X > 39 THEN X=0 +90 IF X < 0 THEN X=39 +100 IF Y > 39 THEN Y=0 +110 IF Y < 0 THEN Y=39 +120 GOTO 40 \ No newline at end of file diff --git a/samples/sample.mandelbrot.txt b/samples/sample.mandelbrot.txt new file mode 100644 index 0000000..55de1cc --- /dev/null +++ b/samples/sample.mandelbrot.txt @@ -0,0 +1,10 @@ +100 REM Mandelbrot Set in B & W +110 HGR:POKE 49234,0:HCOLOR=3 +120 FOR x = 0 TO 279:FOR y = 0 TO 95 +130 x1 = x / 280 * 3 - 2:y1 = y / 191 * 2 - 1 +140 i = 0:s = x1:t = y1:c = 0 +150 s1 = s * s - t * t + x1 +160 t = 2 * s * t + y1:s = s1:c = 1 - c:i = i + 1 +170 IF s * s + t * t < 4 AND i < 117 THEN GOTO 150 +180 IF c = 0 THEN HPLOT x,y:HPLOT x,191 - y +190 NEXT:NEXT \ No newline at end of file diff --git a/samples/sample.mandelbrot2.txt b/samples/sample.mandelbrot2.txt new file mode 100644 index 0000000..e61637d --- /dev/null +++ b/samples/sample.mandelbrot2.txt @@ -0,0 +1,14 @@ +0 REM Mandelbrot Set - in color +1 REM This picks random points to draw, so it will run forever +2 REM and may never fill in the full plane, but it is fast! +10 HGR : POKE 49234,0 +20 DIM co(10) : FOR c = 0 TO 10 : READ d : co(c) = d : NEXT +30 DATA 1, 2, 3, 5, 6, 1, 2, 3, 5, 6, 0 +100 x = INT(RND(1) * 280) : y = INT(RND(1) * 96) +110 x1 = x / 280 * 3 - 2 : y1 = y / 191 * 2 - 1 +120 i = 0:s = x1:t = y1 +130 s1 = s * s - t * t + x1 +140 t = 2 * s * t + y1:s = s1: i = i + 1 +150 IF s * s + t * t < 4 AND i < 20 THEN GOTO 130 +160 c = co(i/2) : IF c THEN HCOLOR= c : HPLOT x,y : HPLOT x,191 - y +170 GOTO 100 diff --git a/samples/sample.pacman.txt b/samples/sample.pacman.txt new file mode 100644 index 0000000..cedf976 --- /dev/null +++ b/samples/sample.pacman.txt @@ -0,0 +1,245 @@ +10 slow=3: level=1: lives=3: score=0 +20 gt$=CHR$(286): ga$=CHR$(287): go$=gt$ +30 ml$=CHR$(267): mr$=CHR$(266): mu$=CHR$(282): md$=CHR$(283): ms$=CHR$(284): mo$=ml$ +40 d$=CHR$(284)+CHR$(282)+CHR$(268)+CHR$(269)+CHR$(270)+CHR$(42) +50 GOSUB 6000 + +100 DIM map(31,23) +101 DATA "9999999999999999999999999999999" +102 DATA "9000000000000009000000000000009" +103 DATA "9299999099999909099999909999929" +104 DATA "9099999099999909099999909999909" +105 DATA "9000000000000000000000000000009" +106 DATA "9099999099099999999909909999909" +107 DATA "9099999099000009000009909999909" +108 DATA "9000000099999909099999900000009" +109 DATA "9999999099999909099999909999999" +110 DATA "9999999099111111111119909999999" +111 DATA "1111111011199999999911101111111" +112 DATA "9999999099111111111119909999999" +113 DATA "9999999099199999999919909999999" +114 DATA "9000000000000009000000000000009" +115 DATA "9299999099999909099999909999929" +116 DATA "9099999099999909099999909999909" +117 DATA "9000099000000000000000009900009" +118 DATA "9999099099099999999909909909999" +119 DATA "9000000099000009000009900000009" +120 DATA "9099999999999909099999999999909" +121 DATA "9099999999999909099999999999909" +122 DATA "9000000000000000000000000000009" +123 DATA "9999999999999999999999999999999" + +150 DIM me(8): DIM gho(4,8) +180 gho(1,1)=12: gho(1,2)=10: gho(1,4)=0 +181 gho(1,5)=-1: gho(1,6)=0: gho(1,7)=0: gho(1,8)=-1 +182 gho(2,1)=18: gho(2,2)=10: gho(2,4)=0 +183 gho(2,5)=1: gho(2,6)=0: gho(2,7)=0: gho(2,8)=1 +184 gho(3,1)=12: gho(3,2)=12: gho(3,4)=0 +185 gho(3,5)=-1: gho(3,6)=0: gho(3,7)=0: gho(3,8)=-1 +186 gho(4,1)=18: gho(4,2)=12: gho(4,4)=0 +187 gho(4,5)=1: gho(4,6)=0: gho(4,7)=0: gho(4,8)=1 +190 me(1)=15: me(2)=17: me(4)=136 +191 me(5)=-1: me(6)=0: me(7)=-1: me(8)=0 + +200 TEXT: HOME +201 PRINT CHR$(272)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(278)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(274) +202 PRINT CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280) +203 PRINT CHR$(280)CHR$(285)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(280)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(285)CHR$(280) +204 PRINT CHR$(280)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(280)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(280) +205 PRINT CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280) +206 PRINT CHR$(280)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(256)CHR$(258)CHR$(271)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(278)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(271)CHR$(256)CHR$(258)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(280) +207 PRINT CHR$(280)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(264)CHR$(264)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(264)CHR$(264)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(280) +208 PRINT CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(264)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(280)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(264)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280) +209 PRINT CHR$(273)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(274)CHR$(271)CHR$(264)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(280)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(264)CHR$(271)CHR$(272)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(275) +210 PRINT CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(275)CHR$(271)CHR$(257)CHR$(259)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(257)CHR$(259)CHR$(271)CHR$(273)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281) +211 PRINT CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(271)CHR$(032)CHR$(032)CHR$(032)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(032)CHR$(032)CHR$(032)CHR$(271)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032) +212 PRINT CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(274)CHR$(271)CHR$(256)CHR$(258)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(032)CHR$(256)CHR$(258)CHR$(271)CHR$(272)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281) +213 PRINT CHR$(272)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(275)CHR$(271)CHR$(257)CHR$(259)CHR$(032)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(278)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(032)CHR$(257)CHR$(259)CHR$(271)CHR$(273)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(274) +214 PRINT CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280) +215 PRINT CHR$(280)CHR$(285)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(280)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(285)CHR$(280) +216 PRINT CHR$(280)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(258)CHR$(264)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(280)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(264)CHR$(256)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(280) +217 PRINT CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(264)CHR$(264)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(264)CHR$(264)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280) +218 PRINT CHR$(276)CHR$(281)CHR$(281)CHR$(281)CHR$(271)CHR$(257)CHR$(259)CHR$(271)CHR$(256)CHR$(258)CHR$(271)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(278)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(271)CHR$(256)CHR$(258)CHR$(271)CHR$(257)CHR$(259)CHR$(271)CHR$(281)CHR$(281)CHR$(281)CHR$(277) +219 PRINT CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(264)CHR$(264)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(264)CHR$(264)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280) +220 PRINT CHR$(280)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(280)CHR$(271)CHR$(256)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(258)CHR$(271)CHR$(280) +221 PRINT CHR$(280)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(280)CHR$(271)CHR$(257)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(265)CHR$(259)CHR$(271)CHR$(280) +222 PRINT CHR$(280)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(271)CHR$(280) +223 PRINT CHR$(273)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(281)CHR$(275) + +300 REM====READ IN MAP==== +305 RESTORE +310 dots=0 +315 HTAB 40: VTAB 8: PRINT "Level: ";: PRINT level; +320 FOR j=1 TO 23 +325 HTAB 40: VTAB 10: PRINT "Finished Loading in: "; +330 HTAB 61: VTAB 10: PRINT 23-j; +335 READ r$ +340 FOR i=1 TO 31: map(i,j)=VAL( MID$( r$, i, 1)) +345 IF map(i,j)=0 THEN dots=dots + 1 +350 IF map(i,j)=2 THEN dots=dots + 1 +355 NEXT +360 NEXT +365 HTAB 40: VTAB 10: PRINT " "; + +400 count=0 +450 me(4)=PEEK (49152): count=count + 1 +452 HTAB 40: VTAB 10: PRINT "Score: ";: PRINT score; +454 HTAB 40: VTAB 12: PRINT "Lives: ";: PRINT lives; +460 IF me(4)=136 THEN me(7)=-1:me(8)=0: REM ==== LEFT +462 IF me(4)=138 THEN me(7)=0:me(8)=1: REM ==== DOWN +464 IF me(4)=139 THEN me(7)=0:me(8)=-1: REM ==== UP +466 IF me(4)=149 THEN me(7)=1:me(8)=0: REM ==== RIGHT +472 IF map(me(1),me(2))=0 THEN dots=dots-1:map(me(1),me(2))=-1:score=score+50 +474 IF map(me(1),me(2))=2 THEN dots=dots-1:map(me(1),me(2))=-1:GOSUB 1000 +476 IF dots=0 THEN GOTO 5000: REM ==== Next Level +478 HTAB me(1): VTAB me(2): PRINT ms$; +490 IF (count/slow) <> INT(count/slow) THEN GOTO 450 + +500 GOSUB 600 +505 IF me(5)=-1 THEN mo$=ml$ +510 IF me(5)=1 THEN mo$=mr$ +511 IF me(6)=-1 THEN mo$=mu$ +511 IF me(6)=1 THEN mo$=md$ +515 HTAB me(1): VTAB me(2): PRINT mo$; +520 FOR wg=1 to 4 +525 IF gho(wg,4) > 0 THEN go$=ga$ +530 IF gho(wg,4) <=0 THEN go$=gt$ +532 IF me(1)=gho(wg,1) THEN IF me(2)=gho(wg,2) THEN GOSUB 550 +534 GOSUB 800 +536 HTAB gho(wg,1): VTAB gho(wg,2): PRINT go$;: gho(wg,4)=gho(wg,4)-1 +538 IF me(1)=gho(wg,1) THEN IF me(2)=gho(wg,2) THEN GOSUB 550 +540 NEXT +545 GOTO 450 + +550 IF gho(wg,4) > 0 THEN GOTO 580: REM EATABLE GHOST +560 POP: GOTO 5100 +580 score=score + prize: prize=prize * 2 +582 gho(wg,1)=15: gho(wg,2)=10: gho(wg,4)=0 +584 gho(wg,5)=1: gho(wg,6)=0: gho(wg,7)=0: gho(wg,8)=1 +586 RETURN + +600 REM====TRY TO MOVE IN NEW DIRECTION==== +605 IF map(me(1)+me(7),me(2)+me(8)) > 2 THEN GOTO 650 +610 HTAB me(1): VTAB me(2): PRINT " "; +615 me(1)=me(1)+me(7): me(2)=me(2)+me(8) +620 me(5)=me(7): me(6)=me(8) +625 IF me(1) <=1 THEN me(1)=30 +630 IF me(1) >=31 THEN me(1)=2 +635 RETURN +650 REM====TRY TO MOVE IN CURRENT DIRECTION==== +655 IF map(me(1)+me(5),me(2)+me(6)) > 2 THEN RETURN +660 HTAB me(1): VTAB me(2): PRINT " "; +665 me(1)=me(1)+me(5): me(2)=me(2)+me(6) +670 IF me(1) <=1 THEN me(1)=30 +675 IF me(1) >=31 THEN me(1)=2 +680 RETURN + +800 REM====TRY TO MOVE GHOST IN NEW DIRECTION==== +805 IF map(gho(wg,1)+gho(wg,7),gho(wg,2)+gho(wg,8)) > 2 THEN GOTO 850 +810 HTAB gho(wg,1): VTAB gho(wg,2) +815 x=map(gho(wg,1),gho(wg,2)): GOSUB 2000 +820 gho(wg,1)=gho(wg,1)+gho(wg,7): gho(wg,2)=gho(wg,2)+gho(wg,8) +825 gho(wg,5)=gho(wg,7): gho(wg,6)=gho(wg,8): GOSUB 900 +830 IF gho(wg,1) <=1 THEN gho(wg,1)=2: gho(wg,5)=gho(wg,5) * -1 +835 IF gho(wg,1) >=31 THEN gho(wg,1)=30: gho(wg,5)=gho(wg,5) * -1 +840 RETURN + +850 REM====TRY TO MOVE GHOST IN CURRENT DIRECTION==== +855 IF map(gho(wg,1)+gho(wg,5),gho(wg,2)+gho(wg,6)) > 2 THEN GOTO 950 +860 HTAB gho(wg,1): VTAB gho(wg,2) +865 x=map(gho(wg,1),gho(wg,2)): GOSUB 2000 +870 gho(wg,1)=gho(wg,1)+gho(wg,5): gho(wg,2)=gho(wg,2)+gho(wg,6) +875 IF gho(wg,1) <=1 THEN gho(wg,1)=2: gho(wg,5)=gho(wg,5) * -1 +880 IF gho(wg,1) >=31 THEN gho(wg,1)=30: gho(wg,5)=gho(wg,5) * -1 +885 RETURN + +900 REM====NEW NEW DIRECTION FOR GHOST ATTACK==== +902 IF gho(wg,4) > 0 THEN GOTO 920 +904 IF gho(wg,7)=0 THEN GOTO 912 +906 REM====NEW VERTICAL==== +908 IF me(2) < gho(wg,2) THEN gho(wg,7)=0: gho(wg,8)=-1: RETURN +910 gho(wg,7)=0: gho(wg,8)=1: RETURN +912 REM====NEW HORIZONTAL==== +914 IF me(1) < gho(wg,1) THEN gho(wg,7)=-1: gho(wg,8)=0: RETURN +916 gho(wg,7)=1: gho(wg,8)=0: RETURN + +920 REM====NEW NEW DIRECTION FOR GHOST RETREAT==== +924 IF gho(wg,7)=0 THEN GOTO 932 +926 REM====NEW VERTICAL==== +928 IF me(2) < gho(wg,2) THEN gho(wg,7)=0: gho(wg,8)=1: RETURN +930 gho(wg,7)=0: gho(wg,8)=-1: RETURN +932 REM====NEW HORIZONTAL==== +934 IF me(1) < gho(wg,1) THEN gho(wg,7)=1: gho(wg,8)=0: RETURN +936 gho(wg,7)=-1: gho(wg,8)=0: RETURN + +950 REM====NEW CURRENT DIRECTION FOR GHOST==== +955 pik=INT(RND(1)*7)+1 +960 IF pik=1 THEN gho(wg,5)=1:gho(wg,6)=0:gho(wg,7)=0:gho(wg,8)=1:RETURN +961 IF pik=2 THEN gho(wg,5)=-1:gho(wg,6)=0:gho(wg,7)=0:gho(wg,8)=1:RETURN +962 IF pik=3 THEN gho(wg,5)=1:gho(wg,6)=0:gho(wg,7)=0:gho(wg,8)=-1:RETURN +963 IF pik=4 THEN gho(wg,5)=-1:gho(wg,6)=0:gho(wg,7)=0:gho(wg,8)=-1:RETURN +964 IF pik=5 THEN gho(wg,5)=0:gho(wg,6)=1:gho(wg,7)=1:gho(wg,8)=0:RETURN +965 IF pik=6 THEN gho(wg,5)=0:gho(wg,6)=-1:gho(wg,7)=1:gho(wg,8)=0:RETURN +966 IF pik=7 THEN gho(wg,5)=0:gho(wg,6)=1:gho(wg,7)=-1:gho(wg,8)=0:RETURN +967 IF pik=8 THEN gho(wg,5)=0:gho(wg,6)=-1:gho(wg,7)=-1:gho(wg,8)=0:RETURN + +1000 FOR i=1 TO 4: gho(i,4)=30: NEXT: prize=2000: RETURN: REM ==== POWER UP + +2000 IF x=0 THEN PRINT CHR$(271);: RETURN +2002 IF x=2 THEN PRINT CHR$(285);: RETURN +2004 PRINT " ";: RETURN + +5000 slow=slow - 1: IF slow < 1 THEN slow=1 +5010 level=level + 1 +5020 GOTO 180 + +5100 lives=lives - 1 +5110 FOR j=1 TO 6: HTAB me(1): VTAB me(2): PRINT MID$( d$, j, 1); +5115 FOR k=1 to 300: NEXT: NEXT +5120 IF lives=0 THEN GOTO 5500 +5125 FOR j=1 TO 4: HTAB gho(j,1): VTAB gho(j,2) +5126 x=map(gho(j,1),gho(j,2)): GOSUB 2000: NEXT +5130 me(1)=15: me(2)=17: me(4)=136 +5132 me(5)=-1: me(6)=0: me(7)=-1: me(8)=0 +5134 gho(1,1)=12: gho(1,2)=10: gho(1,4)=0 +5136 gho(1,5)=-1: gho(1,6)=0: gho(1,7)=0: gho(1,8)=-1 +5138 gho(2,1)=18: gho(2,2)=10: gho(2,4)=0 +5140 gho(2,5)=1: gho(2,6)=0: gho(2,7)=0: gho(2,8)=1 +5142 gho(3,1)=12: gho(3,2)=12: gho(3,4)=0 +5144 gho(3,5)=-1: gho(3,6)=0: gho(3,7)=0: gho(3,8)=-1 +5146 gho(4,1)=18: gho(4,2)=12: gho(4,4)=0 +5148 gho(4,5)=1: gho(4,6)=0: gho(4,7)=0: gho(4,8)=1 +5149 HTAB me(1): VTAB me(2): PRINT mr$;:FOR k=1 to 300: NEXT +5150 GOTO 400 + +5500 HTAB 40: VTAB 10: PRINT "Score: ";: PRINT score; +5510 HTAB 40: VTAB 12: PRINT "Lives: ";: PRINT lives; +5520 HTAB 40: VTAB 14: PRINT "GAME OVER !"; +5550 END + +6000 PR#3 : TEXT: HOME: HTAB 30: VTAB 5: PRINT "(Not Really) ASCII": PRINT "" +6001 PRINT " MMMMMMMM 8OOOO8: ,"; +6002 PRINT "NI ,M MMM? MM8" +6003 PRINT " MMMMMMMMMN MMM OOOOOOOOOO M"; +6004 PRINT "MM~ MMM MMM~ MMMMN MM7" +6005 PRINT " 8MMMMMMMMM ?MMMM OOOOOOOOOOOO: ~M"; +6006 PRINT "MMM MMMMM MMMM MMMMMN MM:" +6007 PRINT " MMM8O8MMM MMMMMM 8OOOOOOOO$ MM"; +6008 PRINT "MMM~?MMMMMM 7MMMMM NMMMMMN MM " +6009 PRINT " MMMO NMM MM MMMD OOOO8 :MM"; +6010 PRINT "MMMMMM MMMMM, MM MMMM DMMMMMMMMM " +6011 PRINT " ~MMMMMMM MM $MMM OOOOOO8 MM:"; +6012 PRINT " MMMM+ MMMMM MM MMMM 8MMMMMMMMM " +6013 PRINT " MMMD: MMN+8MMMM +OOOOOOOOOO$ :MN "; +6014 PRINT " ,MMM MMMMN ~MM=ZMMMM+ DMM MMMMMM " +6015 PRINT " MMM MMMMMMMMMM 8OOOOOOOOOO8 MM "; +6016 PRINT " 7M OMMMM8 MMMMMMMMMM OMM MMMMM " +6017 PRINT " MM MM MMMMM :OOOOOOOO? $M "; +6018 PRINT " O MMI MM ZMMMM $MM ZMMM " +6019 PRINT " 7 Z =OO= "; +6020 PRINT " N " +6100 HTAB 32: VTAB 18: PRINT "by Michael Kemp" +6105 HTAB 29: VTAB 19: PRINT "tweaks by Joshua Bell" +6110 HTAB 29: VTAB 20: PRINT "Hit ENTER to begin..." +6200 IF PEEK (49152) <> 141 THEN GOTO 6200 +6210 RETURN diff --git a/samples/sample.paint.txt b/samples/sample.paint.txt new file mode 100644 index 0000000..06a99dd --- /dev/null +++ b/samples/sample.paint.txt @@ -0,0 +1,23 @@ +0 REM *** Drawing program using mixed 280x160 mode *** +10 LX = 0 : LY = 0 : PEN = 3 : GOSUB 100 +20 GOSUB 300 +30 VTAB 21 : HTAB 70 : PRINT "("X","Y") " +40 IF X <> LX OR Y <> LY THEN HPLOT TO X, Y : LX = X : LY = Y +50 A = PEEK(49152)-128 : IF A > 0 THEN A$ = CHR$(A) : POKE 49168,0 +60 IF A$ >= "1" AND A$ <= "6" THEN PEN = ASC(A$) - ASC("0") : GOSUB 200 +70 IF A$ = " " THEN GOSUB 100 +80 IF A$ = CHR$(27) THEN END +90 A$ = CHR$(0) : GOTO 20 +100 REM ** Show Menu ** +110 PR#3 : HOME : HGR : HCOLOR= 3 : FOR Y = 150 TO 160 : HPLOT 0,Y TO 279,Y : NEXT Y +120 FOR HC = 1 TO 6 : HCOLOR= HC +130 FOR Y = 152 TO 159 : HPLOT 10+14*HC,Y TO 23+14*HC,Y : NEXT Y +140 NEXT HC +150 VTAB 21 : PRINT "COLOR: 1 2 3 4 5 6"; +160 HTAB 60 : PRINT "POSITION:" : FOR N = 1 TO 8 : PRINT "=========="; : NEXT N +170 PRINT "Instructions: Joystick draws. 1-6 chooses colors. Space clears. Esc quits."; +200 HCOLOR= PEN : FOR Y = 154 TO 157 : HPLOT 5,Y TO 15,Y : NEXT Y +210 GOSUB 300 : HPLOT X, Y : RETURN + +300 X = INT(PDL(0)/255*279) : Y = INT(PDL(1)/255*191) : IF Y > 149 THEN Y = 149 +310 RETURN diff --git a/samples/sample.primes.txt b/samples/sample.primes.txt new file mode 100644 index 0000000..2fdcb57 --- /dev/null +++ b/samples/sample.primes.txt @@ -0,0 +1,29 @@ +10 text : home +20 print "Prime numbers" +30 print " "; +40 for x = 1 to 1000 +50 gosub 1000 +60 if p == 1 then print x;" "; +70 next +80 print +90 end +1000 rem ** subroutine to check for prime ** +1010 rem number to be checked is stored in x +1020 rem d is used for divisor +1030 rem q is used for quotient +1040 rem p is used for return value, if x is prime, p will be 1, else 0 +1050 p = 0 +1060 if x < 2 OR x <> int(x) goto 1180 +1070 if x == 2 OR x == 3 OR x == 5 then p=1 : goto 1180 +1080 if x/2 == int(x/2) goto 1180 +1090 if x/3 == int(x/3) goto 1180 +1100 d = 5 +1110 q = x/d : if q == int(q) goto 1180 +1120 d = d + 2 +1130 if d*d> x goto 1170 +1140 q = x/d : if q == int(q) goto 1180 +1150 d = d + 4 +1160 if d*d <= x goto 1110 +1170 p = 1 +1180 return +1190 rem ** end of subroutine to check for prime ** diff --git a/samples/sample.puzzler.txt b/samples/sample.puzzler.txt new file mode 100644 index 0000000..430a633 --- /dev/null +++ b/samples/sample.puzzler.txt @@ -0,0 +1,85 @@ + 0 PR#0 + 10 DIM PP(16),NU(16) + 20 POKE - 16368,0 + 30 TEXT : HOME : VTAB 4: HTAB 14: PRINT "THE PUZZLER" + 40 VTAB 15: HTAB 12: PRINT "BY GREGG BUNTIN" + 50 FOR I = 1 TO 2000: NEXT I + 60 VTAB 20: PRINT "DO YOU WISH INSTRUCTIONS ";: INPUT I$ + 70 IF I$ < > "Y" THEN 190 + 80 HOME : VTAB 2: HTAB 14: PRINT "THE PUZZLER" + 90 VTAB 4: PRINT "THE OBJECT OF THIS GAME IS TO GET ALL OF": PRINT "THE NUMBERS IN ORDER FROM 1 TO 15" + 100 PRINT "THE COMMANDS ARE" SPC( 13);: INVERSE : PRINT "A": NORMAL : HTAB 30: PRINT ":": HTAB 30: PRINT ":" + 110 HTAB 25: INVERSE : PRINT "<-";: NORMAL : PRINT " - ";: INVERSE : PRINT "->": NORMAL + 120 : HTAB 30: PRINT ":": HTAB 30: PRINT ":": INVERSE : HTAB 30: PRINT "Z": NORMAL + 130 PRINT : PRINT "BY MEANS OF THESE COMMANDS YOU WILL ": PRINT "EXCHANGE THE BLANK SPACE WITH THE NUMBER";: PRINT "IN THE UP,DOWN,LEFT OR RIGHT POSITIONS" + 150 : VTAB 21: PRINT SPC( 8)"PRESS TO START GAME" + 160 K = PEEK ( - 16384): IF K < 127 THEN 160 + 170 IF K = 155 THEN 190 + 180 GOTO 160 + 190 POKE - 16368,0: HOME : VTAB 4: HTAB 14: PRINT "THE PUZZLER": VTAB 12 + 200 PRINT "Type N to start a (N)EW GAME" + 220 K = PEEK ( - 16384): IF K < 127 THEN 220 + 230 IF K = 206 THEN 260 + 240 IF K = 211 THEN 740 + 250 GOTO 220 + 260 HOME : PRINT "SCRAMBLING PUZZLE.............." + 261 FOR I = 1 TO 16 + 270 Q = INT ( RND (1) * 16) + 1 + 280 IF PP(Q) THEN 270 + 290 PP(Q) = 1:NU(I) = Q: NEXT + 300 TEXT : HOME : GR : COLOR= 12 + 310 FOR I = 0 TO 19: HLIN 0 + I,39 - I AT I: HLIN 0 + I,39 - I AT 39 - I + 320 VLIN 0 + I,39 - I AT I: VLIN 0 + I,39 - I AT 39 - I: NEXT + 330 COLOR= 1: FOR I = 9 TO 29 STEP 10: HLIN 0,39 AT I: VLIN 0,39 AT I: NEXT + 340 COLOR= 0: HLIN 0,39 AT 39: VLIN 0,39 AT 39 + 350 FOR I = 1 TO 16:FLAG = 1:PL = I: GOSUB 370 + 360 NEXT I: GOTO 520 + 370 IF PL = 1 OR PL = 5 OR PL = 9 OR PL = 13 THEN X = 1 + 380 IF NU(PL) = 16 THEN RETURN + 390 IF PL = 2 OR PL = 6 OR PL = 10 OR PL = 14 THEN X = 11 + 400 IF PL = 3 OR PL = 7 OR PL = 11 OR PL = 15 THEN X = 21 + 410 IF PL = 4 OR PL = 8 OR PL = 12 OR PL = 16 THEN X = 31 + 420 IF PL < 5 THEN Y = 2 + 430 IF PL > 4 AND PL < 9 THEN Y = 12 + 440 IF PL > 8 AND PL < 13 THEN Y = 22 + 450 IF PL > 12 THEN Y = 32 + 460 COLOR= 12: IF FLAG = 1 THEN COLOR= 2:FLAG = 0 + 470 IF NU(PL) > 9 THEN 500 + 480 X = X + 2 + 490 ON NU(PL) GOTO 850,860,870,880,890,900,910,920,930,1100,1110 + 500 GOSUB 850:X = X + 4 + 510 ON NU(PL) - 9 GOTO 840,850,860,870,880,890 + 520 FOR I = 1 TO 16: IF NU(I) = 16 THEN PL = I: GOTO 540 + 530 NEXT + 540 K = PEEK ( - 16384): IF K < 127 THEN 540 + 545 POKE - 16368,0 + 550 IF K = 193 THEN 630 + 560 IF K = 218 THEN 650 + 570 IF K = 136 THEN 670 + 580 IF K = 149 THEN 690 + 610 IF K = 155 THEN TEXT : HOME : PRINT "BYE-BYE": END + 620 GOTO 540 + 630 IF PL < 5 THEN 520 + 640 A = - 4: GOTO 710 + 650 IF PL > 12 THEN 520 + 660 A = 4: GOTO 710 + 670 IF PL = 1 OR PL = 5 OR PL = 9 OR PL = 13 THEN 520 + 680 A = - 1: GOTO 710 + 690 IF PL = 4 OR PL = 8 OR PL = 12 OR PL = 16 THEN 520 + 700 A = 1: GOTO 710 + 710 T = PL:PL = PL + A:FLAG = 0: GOSUB 370 + 720 NU(T) = NU(PL):NU(PL) = 16:PL = PL - A + 730 FLAG = 1: GOSUB 370: GOTO 520 + 830 END + 840 VLIN Y,Y + 5 AT X: VLIN Y,Y + 5 AT X + 2: PLOT X + 1,Y: PLOT X + 1,Y + 5: RETURN + 850 VLIN Y,Y + 5 AT X + 1: PLOT X,Y: HLIN X,X + 2 AT Y + 5: RETURN + 860 HLIN X,X + 2 AT Y: VLIN Y,Y + 2 AT X + 2: PLOT X + 1,Y + 2: VLIN Y + 3,Y + 5 AT X: HLIN X,X + 2 AT Y + 5: RETURN + 870 HLIN X,X + 2 AT Y: HLIN X + 1,X + 2 AT Y + 2: HLIN X,X + 2 AT Y + 5: VLIN Y,Y + 5 AT X + 2: RETURN + 880 VLIN Y,Y + 5 AT X + 2: VLIN Y,Y + 2 AT X: PLOT X + 1,Y + 2: RETURN + 890 HLIN X,X + 2 AT Y: VLIN Y,Y + 2 AT X: PLOT X + 1,Y + 2: VLIN Y + 3,Y + 4 AT X + 2: HLIN X,X + 1 AT Y + 5: RETURN + 900 VLIN Y + 1,Y + 5 AT X: HLIN X + 1,X + 2 AT Y: VLIN Y + 2,Y + 5 AT X + 2: HLIN X,X + 2 AT Y + 2: HLIN X,X + 2 AT Y + 5: RETURN + 910 HLIN X,X + 2 AT Y: VLIN Y,Y + 5 AT X + 2: RETURN + 920 VLIN Y,Y + 5 AT X: VLIN Y,Y + 5 AT X + 2: PLOT X + 1,Y: PLOT X + 1,Y + 2: PLOT X + 1,Y + 5: RETURN + 930 HLIN X,X + 2 AT Y: VLIN Y + 1,Y + 5 AT X + 2: HLIN X,X + 2 AT Y + 2: VLIN Y,Y + 2 AT X: HLIN X,X + 1 AT Y + 5: RETURN + + diff --git a/samples/sample.raindrops.txt b/samples/sample.raindrops.txt new file mode 100644 index 0000000..cfaa37a --- /dev/null +++ b/samples/sample.raindrops.txt @@ -0,0 +1,199 @@ +0 REM Nicdem25's awesome game +100 REM Catch the raindrop +101 rem Game design by Nicholas Merchant, age 10 +102 rem Programming mostly by his dad with Nicholas +103 rem version 1.7, August 2011 +111 clear: home + + +115 print " Nicdem25games":? +:?" CATCH THE RAINDROP":? +116 print " Version 1.7": +:? " August 2011":? +117 rem print " Programmed by JRM":? +118 rem print " Concept by Nicholas Merchant" + +121 ?:?"Game controls: ":? +122 ?" Left arrow (move left)" +123 ?" Right arrow (move right)" +124 ?" (pause game) +125 ?" Q (quit)." +126 ? + +130 ?"Powerdrops:" +131 ?" + = extra life" +133 ?" $ = 10 points" +134 ?" s = slow down" +135 ? +140 ?: Input "Press to begin.";A$ + +150 home +151 let level = 1 +152 let lives = 3 +155 let D$="*": rem default raindrop character +156 let pwl = 2: rem length of paddle expansion when powerup is caught + +170 let bottomofscreen = 17: rem variable for how far the rain falls +180 let sp = 2000: rem sp is the variable that controls speed of rain +189 REM draw the bottom of screen +190 for a = 1 to 40: vtab bottomofscreen +1: htab a: ?"^";:next a +196 vtab bottomofscreen +3:?" Nicdem25: Catch the raindrop" +197 vtab 23:print "Score: "score" Level: "level" Lives: "lives; + + +191 REM Initial paddle position variable: p1 is the horizontal offset +192 REM PL is the paddle length in characters +193 let p1 = 18 +194 let oldpos = p1 +195 let PL = 10:let OPL = PL: rem OPL is the original paddle length + + +200 REM ++++++++++++++++++++++++++++ +201 rem subroutine: falling raindrop +202 rem ++++++++++++++++++++++++++++ + + +230 x = RND (-RND (1)): rem reseed random number +240 let x = int(rnd(1)*30)+5 +241 rem assign a random x axis value for drop, 5<=x<=35 + +250 for y = 1 to bottomofscreen - 1 +260 htab x: vtab y + 1 +270 print D$;:rem draw drop at position + +271 rem delay loop controls speed: speed increases with level up to max +275 for n = 1 to sp: next n + +276 gosub 900: rem do paddle subroutine + +278 htab x: vtab y + 1: ?" ":rem erase old drop +279 next y + + + +280 REM did you catch the raindrop? +284 rem missed the drop +285 if x < p1 or x > p1+PL then lives = lives -1:goto 320 + +290 rem caught the drop +291 print chr$(7): REM make a sound for catching the drop +292 let score = score + 1 +293 if D$ = "+" then let lives = lives + 1 +294 if D$ = "E" then gosub 2000: rem expand paddle, set power timer +295 if D$ = "s" then let sp=sp+350: rem s slows down drops +296 if D$ = "$" then let score = score + 9:if score/10 <> int(score/10) then let level = level + 1 + + + +300 rem check if score is a multiple of 10: if so, level up +303 if score/10 = int(score/10) then let level = level + 1:let counter=1 + +304 rem every five levels, add a life +305 if counter =1 and level/5 = int(level/5) then let counter=0:gosub 700 + +309 rem speed up if score is a multiple of 10 +310 if score/10 = int(score/10) then gosub 800 + +314 rem powertime counter: expanded paddle length lasts five raindrops +315 rem let ptime = ptime - 1 +316 rem if ptime < 0 then let ptime = 0 +317 rem if ptime = 0 then let PL = OPL + +320 if lives = -1 then goto 9000:rem lost last life: go to end routine + +340 vtab 23 +350 print "Score: "score" Level: "level" Lives: "lives" "; + +400 REM powerups: powerup 1 = expand, powerup 2 = extra life +405 let powerup = 0 + +410 n = RND (-RND (1)): rem reseed random number +511 let n = rnd(1) +515 if n < 0.15 then let powerup = 1 +520 if n >= 0.2 and n < 0.3 then let powerup = 2 +530 if n >= 0.3 and n < 0.4 then let powerup = 3 + +550 rem powerup characters +560 if powerup = 0 then let D$ = "*" +570 if powerup = 1 then let D$ = "+" +580 if powerup = 2 then let D$ = "s" +590 if powerup = 3 then let D$ = "$" + + +600 goto 200:rem go back and start a new raindrop + +700 rem ++++++ +710 rem lives up subroutine +720 rem ++++++ +730 if (int(score/10)+1)/5 = (int(int(score/10)+1))/5 then let lives = lives +2 +750 return + + +800 rem +++++++ +810 rem speed up subroutine +820 rem ++++++ +850 let sp = sp - ((level-1)*100) +855 if sp < 400 then let sp = 400 +890 return + + +900 REM ++++++++++++++++++++++++++++++++++++++++ +901 REM GET PLAYER INPUT +902 REM ++++++++++++++++++++++++++++++++++++++++ +903 IF PEEK (49152) > 127 THEN K$=CHR$(PEEK (49152)-128): REM SEE IF KEY(S) PRESSED +904 IF K$ = "Q" THEN goto 9000 +905 if K$ = " " then gosub 5000 +924 let oldpos = p1 +935 if K$ = CHR$(8) then let p1 = p1 - 1 +946 if K$ = CHR$(21) then let p1 = p1 + 1 +950 if p1 < 1 then let p1 = 1 +965 if p1 > 40-PL then let p1 = 40-PL +979 POKE 49168,0: REM reset keyboard input address (clear keyboard strobe) + + +999 REM +++++++++++ +1000 REM Draw paddle +1001 rem +++++++++++ + +1215 for b = 0 to PL +1210 vtab bottomofscreen: htab p1 + b: ?"-"; +1211 next b + +1212 if oldpos < p1 then gosub 1220 +1214 if oldpos > p1 then gosub 1225 + +1219 return + +1220 REM erase old left edge of paddle subroutine +1221 vtab bottomofscreen: htab oldpos: ?" "; +1224 return + +1225 REM erase old right edge of paddle subroutine +1228 vtab bottomofscreen: htab oldpos + PL: ?" "; +1230 return + +1500 rem erase expanded paddle when power time is up +1510 for i = 1 to pwl +1515 if oldpos + i > 40 then goto 1530 +1520 htab oldpos + i: ?" "; +1530 next i +1550 return + + +2000 REM increase paddle length; set power timer to five drops +2010 let PL=PL+pwl +2020 let ptime = 5 +2030 return + +5000 rem pause +5010 htab 4:vtab 4:input "Paused: press to resume";K$ +5020 htab 4:vtab 4:? " " +5040 let K$ = "" +5050 return + +9000 vtab 11:htab 16:print "GAME OVER":? +9010 print " Play again (Y/N)?" +9015 get A$ +9020 if A$ = "Y" then goto 150 +9030 if A$ = "N" then ?" Bye!":end +9040 goto 9000 diff --git a/samples/sample.readsector.txt b/samples/sample.readsector.txt new file mode 100644 index 0000000..b6771b4 --- /dev/null +++ b/samples/sample.readsector.txt @@ -0,0 +1,11 @@ +10 PR#0 : TEXT : HOME +20 INPUT "Sector filename: "; FI$ +30 HOME + +100 PRINT CHR$(4);"OPEN ";FI$;",L50" +110 PRINT CHR$(4);"READ ";FI$;",R0" +120 INPUT R : REM Number of records +130 FOR A = 1 TO R +140 PRINT CHR$(4);"READ ";FI$;",R";A +150 INPUT A$ : PRINT A$ +160 NEXT diff --git a/samples/sample.rodscolorpattern.txt b/samples/sample.rodscolorpattern.txt new file mode 100644 index 0000000..81c0a6d --- /dev/null +++ b/samples/sample.rodscolorpattern.txt @@ -0,0 +1,11 @@ +0 REM Rod's Color Pattern +10 GR : ONERR GOTO 99 +20 FOR W = 3 TO 50 +30 FOR I = 1 TO 19 +40 FOR J = 0 TO 19 +50 K = I + J +60 COLOR= J * 3 / (I + 3) + I * W / 12 +70 PLOT I,K: PLOT K,I: PLOT 40 - I,40 - K: PLOT 40 - K,40 - I +80 PLOT K,40 - I: PLOT 40 - I,K: PLOT I,40 - K: PLOT 40 - K,I +90 NEXT : NEXT : NEXT : GOTO 20 +99 TEXT : HOME : END diff --git a/samples/sample.scribble.txt b/samples/sample.scribble.txt new file mode 100644 index 0000000..e1cd685 --- /dev/null +++ b/samples/sample.scribble.txt @@ -0,0 +1,24 @@ +10 HOME:VTAB21:HTAB16:?"SCRIBBLE" +14 M=200 +15 HGR:DIM OX(M),OY(M):I=0:J=1-M +20 OX(I)=140:OY(I)=80:X=OX(I):Y=OY(I):SX=0:SY=0 +30 C=1+3*RND(1):IF RND(1)<0.5 THEN C=C+4 +31 HCOLOR=C +33 HPLOT OX(I),OY(I) TO X,Y +35 SX=SX+1-2*RND(1):SY=SY+1-2*RND(1) +36 IF SX < 0 AND X<70 THEN SX=SX*X/50 +37 IF SX > 0 AND X>210 THEN SX=SX*(279-X)/50 +38 IF SY < 0 AND Y<40 THEN SY=SY*Y/30 +39 IF SY > 0 AND Y>120 THEN SY=SY*(159-Y)/30 +41 J=J+1:IF J>M THEN J=0 +42 I=I+1:IF I>M THEN I=0 +43 IF J<0 THEN 45 +44 HCOLOR=0:HPLOT OX(I),OY(I) TO OX(J),OY(J):HCOLOR=3 +45 OX(I)=X:OY(I)=Y +46 X=X+SX:Y=Y+SY +50 IF X>=0 THEN 70 +60 X=0:GOTO 80 +70 IF X>=280 THEN X=279 +80 IF Y>=0 THEN 100 +90 IF Y>=160 THEN Y=159 +100 GOTO 30 diff --git a/samples/sample.sectorgen.txt b/samples/sample.sectorgen.txt new file mode 100644 index 0000000..771f897 --- /dev/null +++ b/samples/sample.sectorgen.txt @@ -0,0 +1,423 @@ +0 REM From Challenge Magazine #26, by Marc Miller + +0 REM *** CORRECTIONS *** +0 REM 1220 Missing "once" and spacing +0 REM 1230 Missing INPUT +0 REM 1253 Typo: "C" -> "CH" for Chirper +0 REM 2050 DR$ initialized with " should be "" +0 REM 2070 LO$(B( should be LO$(B) +0 REM 2130 Unnecessary GOTO 2140 +0 REM 2740 REM / merged with subsequent line +0 REM 3015 Typo: "O" -> "OR" +0 REM 3020 Typo: "HY 9" --> "HY = 9" +0 REM 3550 Typo: "AM 10" --> "AM = 10" +0 REM 3820 Typo: <> " should be <> "" +0 REM 4320 "(5-ST)" should be "(5-S1)" +0 REM Typo: line 4460 printed as 460 +0 REM 4530 "ST = -3" should be "DM = -3" +0 REM 4622 "DM = +1" unary plus unnecessary +0 REM 4624 "D = 3" should be "DM = 3" +0 REM 5030 "ST$="B" AND ST$="C"" should be "ST$="B" OR ST$="C"" +0 REM 6210 " " should be 15 spaces +0 REM 6625 DR$ initialized with " should be "" +0 REM 6650 goto target missing; split 6640 to ensure AL$ appended if DR$ set +0 REM 2070 Missing ) at end of SQR +0 REM 2070 Unnecessary GOTO 2080 + +0 REM *** INVESTIGATE *** +0 REM 6120 Rule seems bogus - verify? +0 REM 4150/4160 inverted? +0 REM 4120 Jump to 4150 leaves DM unset, must be incorrect; changed to 4120 (no bases if ST$ = "E" or "X") + +0 PR#0 + +1000 TEXT : HOME : PRINT "Traveller Sector Generator" +1010 PRINT " This program generates world UPP data" +1020 PRINT " for Traveller. Copyright 1986 GDW, Inc." +1100 HX$ = "0123456789ABCDFGHJKLMNPQRSTUVWXYZ" +1105 SP$ = "AAAABBCCDEEX" +1110 BA$ = "ABCDEFGHJKLMNPQRSTUVWXYZ" +1140 DEF FN A(X) = INT ( RND (4) * 6) + 1 +1150 DEF FN B(X) = FN A(X) + FN A(X) + +1200 REM DETERMINE ALLEGIANCES +1210 PRINT : PRINT "Allegiances." +1220 PRINT " You may assign up to 10 allegiances (with a base location and a radius for each). The same allegiance may be used more than once (to allow non-circular regions).": PRINT +1230 INPUT "How many allegiances in the area? > ";A: IF A<1 OR A>10 THEN 1230 +1240 HOME : PRINT "Allegiances" +1250 PRINT " Allegiances are two-letter codes. The following use special procedures in this program:" +1253 PRINT "A* CS CH DR HV IM KK NA SO V* Z*" +1254 PRINT "(* = Wildcard)" +1260 PRINT : PRINT " The first allegiance is the default (automatic) allegiance for the sector.": PRINT +1270 FOR B = 1 TO A +1280 PRINT "Allegiance ";B; +1290 INPUT " is: ";AL$(B):AL$(B) = LEFT$ (AL$(B) + "BB",2) +1300 IF B = 1 THEN LO$(B) = "1620":RA(B) = 22: GOTO 1330 +1310 INPUT "Location (Hex) is: ";LO$(B):LO$(B) = LEFT$ (LO$(B) + "0000",4) +1320 INPUT "Radius (parsecs) is: ";RA(B) +1325 IF RA(B)<1 THEN RA(B) = 1 +1330 NEXT B + +1400 REM DESIGNATE DENSITIES +1410 HOME : PRINT "Densities" +1420 PRINT " You may assign up to 10 densities (with a base location and a radius for each).": PRINT +1430 INPUT "How many densities in the area? > ";A1 +1435 IF A1<1 OR A1>10 THEN 1430 +1440 PRINT " Densities are decimal fractions.": PRINT +1450 PRINT " The first density is the default (automatic) density for the sector.": PRINT +1460 FOR B = 1 TO A1 +1470 PRINT "Density ";B; +1480 INPUT " is: ";DE(B): IF DE(B)>1 THEN 1480 +1490 IF B = 1 THEN L1$(B) = "1620":RD(B) = 22: GOTO 1520 +1500 INPUT "Location (hex) is: ";L1$(B):L1$(B) = LEFT$ (L1$(B) + "0000",4) +1510 INPUT "Radius (parsecs) is: ";RD(B) +1515 IF RD(B)<1 THEN RD(B) = 1 +1520 NEXT B +1530 HOME + +2000 REM PRODUCE SECTOR +2010 PRINT CHR$ (4);"OPEN SECTOR, L50" +2020 FOR X = 1 TO 32 +2030 FOR Y = 1 TO 40 + +2040 REM FIND ALLEGIANCE +2050 DR$ = "":AL$ = AL$(1):DR = 0 +2060 FOR B = A TO 2 STEP - 1 +2070 D = SQR((VAL(LEFT$(LO$(B),2))-X)*(VAL(LEFT$(LO$(B),2))-X)+(VAL(MID$(LO$(B),3,2))-Y)*(VAL(MID$(LO$(B),3,2))-Y)): IF D(0.9*RA(B)) AND FN B(4)>9 THEN AL$="NA": IF FN B(4)>6 THEN AL$="CS" : GOTO 2080 +2080 NEXT B + +2100 REM WORLD OCCURRENCE +2110 DE = DE(1): IF A1<2 THEN 2150 +2120 FOR B = A1 TO 2 STEP - 1 +2130 D = SQR (( VAL ( LEFT$ (L1$(B),2)) - X) * ( VAL ( LEFT$ (L1$(B),2)) - X) - ( VAL ( MID$ (L1$(B),3,2)) - Y) * ( VAL ( MID$ (L1$(B),3,2)) - Y)): IF DDE THEN 7070 + +2200 REM GENERATOR WORLD UPP +2210 ST = FN B(4):ST$ = MID$ (SP$,ST,1) +2220 SI = FN B(4) - 2: IF AL$ = "DR" THEN SI = FN A(6) +2230 AM = FN B(2) - 7 + SI:AM = AM * (AM>0): IF SI = 0 THEN AM = 0 +2240 HY = FN B(2) - 7 + SI: IF SI<2 THEN HY = 0 +2250 IF AM<2 OR AM>9 THEN HY = HY - 4 +2260 IF HY<0 THEN HY = 0 +2270 IF HY>10 THEN HY = 10 +2300 PO = FN B(3) - 2 +2310 GO = FN B(3) - 7 + PO:GO = GO * (GO>0) +2320 LA = FN B(4) - 7 + GO:LA = LA * (LA>0) +2330 IF PO<1 THEN 2600 + +2400 REM FIND DROYNE PRESENCE +2410 DM = - 5: IF SI>0 THEN DM = 0: IF SI>1 THEN DM = 1: IF SI>2 THEN DM = 2: IF SI>3 THEN DM = 3: IF SI>4 THEN DM = 2: IF SI>5 THEN DM = 1: IF SI>6 THEN DM = 0: IF SI>7 THEN DM = - 2: IF SI>8 THEN DM = - 4: IF SI>9 THEN DM = - 6 +2420 DN = - 5: IF AM>0 THEN DN = - 4: IF AM>1 THEN DN = - 3: IF AM>2 THEN DN = - 2: IF AM>3 THEN DN = - 1: IF AM>4 THEN DN = 0: IF AM>5 THEN DN = 2: IF AM>6 THEN DN = 1: IF AM>7 THEN DN = 4: IF AM>8 THEN DN = 3: IF AM>9 THEN DN = - 5 +2430 IF AM>10 THEN DN = - 6: IF AM>11 THEN DN = - 7: IF AM>12 THEN DN = - 3 +2440 DO = 1: IF HY<3 THEN DO = 0: IF HY = 0 THEN DO = - 1 +2450 IF HY>7 THEN DO = 0: IF HY>9 THEN DO = - 3 +2460 DP = - 5: IF PO>0 THEN DP = - 4: IF PO>1 THEN DP = - 3: IF PO>2 THEN DP = - 2: IF PO>3 THEN DP = - 1: IF PO>5 THEN DP = 1: IF PO>7 THEN DP = 0: IF PO>8 THEN DP = - 2 +2470 RR = FN B(5):RL = FN B(5) +2480 DM = DM + DN + DO + DP + RR +2490 IF DM<( - 8) THEN 2600 +2500 IF (DM> - 9) AND (RL>11) THEN DR = - 5:DR$ = "DR" +2510 IF (DM>0) AND (RL>10) THEN DR = - 4:DR$ = "DR" +2520 IF (DM>9) AND (RL>9) THEN DR = - 2:DR$ = "DR" +2530 IF (DM>15) AND (RL>8) THEN DR = 0:DR$ = "DR" +2540 IF DR$ = "" THEN 2600 +2550 IF FN B(4)>5 THEN DR$ = "CH" +2560 PP = ( FN B(3) - 2) + DR: IF PP<0 THEN PP = 0 +2570 IF PP>9 THEN PP = 9 +2580 DR$ = LEFT$ (DR$,1) + STR$ (PP) + +2600 REM FIND SPECIFIC ALLEGIANCE +2610 IF LEFT$ (AL$,1) = "A" THEN 2700 +2620 IF AL$ = "CH" THEN 2800 +2630 IF AL$ = "DR" THEN 2800 +2640 IF AL$ = "HV" THEN 2900 +2650 IF AL$ = "KK" THEN 3000 +2660 IF AL$ = "SO" THEN 3100 +2670 IF LEFT$ (AL$,1) = "V" THEN 3200 +2680 IF LEFT$ (AL$,1) = "Z" THEN 3300 +2690 GOTO 3400 + +2700 REM ASLAN +2705 IF ASC ( MID$ (AL$,2,1))<48 OR ASC ( MID$ (AL$,2,1))>57 THEN 2720 +2710 GO = 20: IF PO<4 AND FN B(6)<11 THEN GO = 16 +2715 GOTO 2730 +2720 WD = FN A(4):RD = FN A(3) + (1 * (PO<4)) + (2 * (PO = 9)) + (3 * (PO = 10)): IF RD<0 THEN WD = 0 +2725 GO = 16 + WD: IF RD>6 THEN GO = 17 +2730 AR = VAL ( MID$ (AL$,2,1)): IF GO = 20 AND AR = 0 AND MID$ (AL$,2,1)<>"0" THEN AL$ = "A" + STR$ ( INT ( RND (5) * 10)) +2735 LA = FN B(5) +2740 REM +2745 DM = 3: IF ST>4 THEN DM = 2: IF ST>6 THEN DM = 0: IF ST>8 THEN DM = - 1: IF ST>9 THEN DM = - 2 +2750 IF PO<3 AND GO = 16 THEN DM = DM - 3: GOTO 2760 +2755 IF PO<8 THEN DM = DM - 1: IF PO<7 THEN DM = DM - 1 +2760 TL = FN A(4) + 8 + DM: IF TL>14 THEN TL = 14 +2765 GOTO 3600 + +2800 REM DROYNE +2810 IF AL$ = "DR" OR AL$ = "CH" THEN PO = FN A(4) + 2 +2820 IF AL$ = "DR" THEN A = FN A(4):GO = 31: IF A<5 THEN GO = 7: IF A<3 THEN GO = 6 +2830 LA = ( FN B(4) - 6) + PO:TL = ( FN B(5) + FN A(3)) - 2 +2835 ST = ( FN B(4) - 7) + TL +2840 LA = LA * (LA>0):TL = TL * (TL>0):ST = ST * (ST>0) +2850 IF ST>12 THEN ST = 12 +2860 ST$ = MID$ ("XXXXEEDCCBBAAAA",ST + 1,1) +2870 GOTO 3700 + +2900 REM HIVERS +2905 IF PO<1 THEN GO = 0:LA = 0:TL = 0: GOTO 3700 +2910 NH = 0: IF ((AM>0 AND AM<5) OR (AM>9 AND AM<13)) AND FN B(5)>8 AND PO>0 THEN NH = 1 +2915 GO = PO - FN A(6): IF GO<0 THEN GO = 0 +2920 IF GO = 4 OR GO = 5 THEN GO = 26 +2925 IF GO = 6 OR GO = 7 THEN GO = 27 +2930 IF GO = 8 THEN GO = 28 +2935 IF GO = 9 THEN GO = 29 +2940 IF GO = 3 THEN GO = 6 +2945 IF PO<7 AND NH = 1 THEN GO = 6 +2950 LA = FN A(4): IF NH = 1 THEN LA = FN B(5) +2955 DM = 3: IF ST$>"A" THEN DM = 2: IF ST$>"B" THEN DM = 0: IF ST$>"C" THEN DM = - 1: IF ST$>"D" THEN DM = - 2 +2960 IF (PO<4 AND GO<>6) THEN DM = DM - 3 +2965 IF (PO>3 AND PO<7) THEN DM = DM - 2 +2970 IF PO = 7 THEN DM = DM - 2 +2975 TL = FN B(4) + 8 + DM +2980 IF TL>15 THEN TL = 15 +2985 GOTO 3700 + +3000 REM KKREE +3005 GO = 23: IF PO>2 THEN GO = 24: IF PO>5 THEN GO = 25 +3010 DM = (2 * (ST$ = "A")) + (ST$ = "B") + ( - 1 * (ST$ = "E")) + ( - 6 * (ST$ = "x")) +3015 DM = DM + ( - 2 * (AM<3)) + ( - 1 * (AM = 3)) + (3 * (AM = 5 OR AM = 6 OR AM = 8)) + ( - 1 * (AM = 10)) + ( - 2 * (AM = 11 OR AM = 13 OR AM = 14 OR AM = 15)) + ( - 3 * (AM = 12)) +3020 DM = DM + ( - 2 * (HY = 0)) + (1 * (HY = 2 OR HY = 6)) + (2 * (HY = 3 OR HY = 4 OR HY = 5)) + ( - 1 * (HY = 8)) + ( - 2 * (HY = 9)) + ( - 3 * (HY = 10)) +3025 NK = 0:PO = FN A(4) - 2 + DM: IF PO>11 THEN PO = 12:NK = 1:PO = FN B(4) - 2:GO = ( FN B(4) - 7) + PO:GO = GO * (GO> - 0):LA = ( FN B(4) - 7) + GO:LA = LA * (LA>0): GOTO 3040 +3030 GO = 23: IF PO>2 THEN GO = 24: IF PO>5 THEN GO = 25 +3035 LA = 19 +3040 IF PO<1 THEN PO = 0:ST = 10:ST$ = "E":GO = 0:LA = 0 +3045 REM +3050 DM = 3: IF ST>4 THEN DM = 2: IF ST>6 THEN DM = 0: IF ST>8 THEN DM = - 1: IF ST>9 THEN DM = - 2: IF ST>11 THEN DM = - 9 +3055 IF GO = 23 THEN DM = DM - 3 +3060 IF GO = 24 THEN DM = DM - 1 +3065 IF GO = 25 THEN DM = DM + 1 +3070 TL = FN A(4) + 9 + DM +3075 IF TL>15 THEN TL = 15 +3080 GOTO 3600 + +3100 REM SOLOMANI +3110 GOTO 3400 + +3200 REM VARGR +3210 IF ( FN B(5) + PO)>15 THEN GO = 7 +3220 GOTO 3400 + +3300 REM ZHODANI +3310 IF ST>11 THEN PO = FN A(4) + 4 +3320 GOTO 3400 + +3400 REM FIND TECH LEVEL +3410 TL = FN A(6) +3420 IF ST$ = "A" THEN TL = TL + 6 +3430 IF ST$ = "B" THEN TL = TL + 4 +3440 IF ST$ = "C" THEN TL = TL + 2 +3450 IF ST$ = "X" THEN TL = TL - 4 +3460 IF SI<5 THEN TL = TL - 1: IF SI<2 THEN TL = TL - 1 +3470 IF AM<4 THEN TL = TL + 1 +3480 IF AM>9 THEN TL = TL + 1 +3490 IF HY>8 THEN TL = TL + 1: IF HY>9 THEN TL = TL + 1 +3500 IF PO>0 AND PO<6 THEN TL = TL + 1 +3510 IF PO>8 THEN TL = TL + 2: IF PO>9 THEN TL = TL + 2 +3520 IF GO = 0 OR GO = 5 THEN TL = TL + 1 +3550 IF LEFT$ (AL$,1) = "Z" AND ((AM<3 AND TL<8) OR (AM = 3 AND TL<7) OR ((AM = 4 OR AM = 7 OR AM = 9) AND TL<6) OR ((AM = 10 OR AM = 11) AND TL<9) OR (AM = 12 AND TL<10)) THEN PO = 0:GO = 0:LA = 0:TL = 0 +3560 GOTO 3700 + +3600 REM BASIC ALIEN TL LEVELLER +3610 IF AM<3 AND TL>7 THEN TL = 7 +3620 IF AM = 3 AND TL<6 THEN TL = 6 +3630 IF (AM = 4 OR AM = 7 OR AM = 9) AND TL<5 THEN TL = 5 +3640 IF (AM = 10 OR AM = 11) AND TL<8 THEN TL = 8 +3650 IF AM = 12 AND TL<9 THEN TL = 9 + +3700 REM GENERATE GAS GIANT +3710 GG = 0: IF FN B(4)<10 THEN GG = 1 + +3800 REM GENERATE TRAVEL ZONES +3810 TZ = 0 +3815 IF AL$<>"IM" THEN 3845 +3820 IF DR$<>"" AND TZ = 0 THEN IF FN B(5)>8 THEN TZ = 1 +3830 IF ST$ = "X" THEN TZ = 2 +3840 IF TZ = 0 AND FN B(4)>10 THEN TZ = 1 +3845 IF LEFT$ (AL$,1)<>"z" THEN 4000 +3850 IF LEFT$ (AL$,1) = "Z" and (st$="C" or ST$="D" or ST$="E") and FNB(5)>10 then tz=4 +3860 IF ST$ = "x" AND LEFT$ (AL$,1) = "z" THEN TZ = 3 + +4000 REM GENERATE BASES +4010 B1 = 0:B2 = 0:B$ = " " +4020 IF LEFT$ (AL$,1) = "A" THEN 4300 +4030 IF AL$ = "DR" THEN 4900 +4040 IF AL$ = "HV" THEN 5000 +4050 IF AL$ = "KK" THEN 4500 +4060 IF AL$ = "SO" THEN 4800 +4070 IF LEFT$ (AL$,1) = "V" THEN 4600 +4080 IF LEFT$ (AL$,1) = "Z" THEN 4700 + +4100 REM IMPERIAL BASES +4110 IF ST$<"C" AND FN B(5)>7 THEN B1 = 1 +4120 IF ST$>"D" THEN 4210 +4130 DM = - 3: IF ST>4 THEN DM = - 2: IF ST>6 THEN DM = - 1: IF ST>8 THEN DM = 0: IF ST>9 THEN 4150 +4140 IF ( FN B(5) + DM)>6 THEN B2 = 1 +4150 IF B1 = 1 AND B2 = 0 THEN B$ = "N" +4160 IF ( FN B(4) + DM)>6 THEN B2 = 1 +4170 IF B1 = 0 AND B2 = 1 THEN B$ = "S" +4180 IF B1 = 1 AND B2 = 1 THEN B$ = "A" +4190 IF (AL$<>"IM" AND AL$<>"CS") AND B1<>0 THEN B$ = "J" +4200 IF (AL$<>"IM" AND AL$<>"CS") AND B2<>0 THEN B$ = "M" +4210 GOTO 6000 + +4300 REM ASLAN BASES +4310 B1 = 0:B2 = 0:T1 = FN B(5):T2 = FN B(4):S1 = ASC (ST$) - 64:B$ = " " +4320 IF GO = 16 AND S1<3 AND T1 + (5 - S1)>13 THEN B1 = 1 +4330 IF GO = 16 AND S1<3 AND T2 + (5 - S1)>12 THEN B2 = 1 +4340 IF GO = 17 AND S1<5 AND T1 + (5 - S1)>8 THEN B1 = 1 +4350 IF GO = 20 AND S1<5 AND T1 + (5 - S1)>6 THEN B1 = 1 +4360 IF GO = 20 AND S1>5 AND T1>7 THEN B1 = 1 +4370 IF GO = 22 AND S1<5 AND T1 + (5 - S1)>9 THEN B1 = 1 +4380 IF (GO = 17 OR GO = 18 OR GO = 21) AND S1<5 AND T2 + (5 - S1)>7 THEN B2 = 1 +4390 IF GO = 19 AND S1<5 AND T2 + (5 - S1)>6 THEN B2 = 1 +4400 IF GO = 22 AND S1<5 AND T2 + (5 - S1)>8 THEN B2 = 1 +4410 IF GO = 18 AND S1>5 AND T2>7 THEN B2 = 1 +4420 IF GO = 19 AND S1>5 AND T2>8 THEN B2 = 1 +4430 IF B1 = 1 THEN B$ = "T" +4440 IF B2 = 1 THEN B$ = "R" +4450 IF B1 = 1 AND B2 = 1 THEN B$ = "U" +4460 IF GO = 16 AND B1 = 1 THEN B$ = "T" +4470 GOTO 6000 + +4500 REM KKREE BASES +4510 IF FN B(5)>6 THEN B1 = 1:B2 = 0:B$ = "K": GOTO 4550 +4520 IF ST$>"D" THEN 4550 +4530 DM = 0: IF ST<9 THEN DM = - 1: IF ST<7 THEN DM = - 2: IF ST<5 THEN DM = - 3 +4540 IF FN B(5) + DM>6 THEN B2 = 1:B$ = "O" +4550 GOTO 6000 + +4600 REM VARGR BASES +4610 IF FN B(5)>6 THEN B1 = 1:B$ = "G": GOTO 4650 +4620 DM = - 2: IF ST>4 THEN DM = - 1: IF ST>6 THEN DM = 2 +4622 IF ST>8 THEN DM = + 1: IF ST>9 THEN DM = 2 +4624 IF ST>11 THEN DM = 3 +4630 IF FN B(5) + DM>8 THEN B2 = 1:B$ = "C" +4640 IF B1 = 1 AND B2 = 1 THEN B$ = "H" +4650 GOTO 6000 + +4700 REM ZHODANI BASES +4710 DM = 2: IF ST>4 THEN DM = 1: IF ST>6 THEN DM = 0: IF ST>9 THEN 4740 +4720 IF FN B(6) + DM>8 THEN B1 = 1:B$ = "Z" +4730 IF ST<5 AND FN B(4)>10 THEN B1 = 2:B$ = "Y" +4740 REM +4750 GOTO 6000 + +4800 REM SOLOMANI BASES +4810 B2 = 0 +4820 IF ST$<"C" AND FN B(5)>7 THEN B1 = 1 +4830 IF B1 = 1 THEN B$ = "J" +4840 GOTO 6000 + +4900 REM DROYNE BASES +4910 IF ST$>"D" THEN 4950 +4920 IF FN B(5) + (4 - ( ASC (ST$) - 64))>7 THEN B1 = 1:B$ = "P" +4930 IF GO = 6 THEN B1 = 2:B$ = "N" +4940 IF ( FN B(5) - 7) + TL>6 THEN B2 = 1:B$ = "Q" +4950 GOTO 6000 + +5000 REM HIVER BASES +5010 B0 = FN B(5):B1 = 0:B2 = 0 +5020 IF ST$ = "A" AND B0<6 THEN B1 = 6 +5030 IF ST$ = "A" AND B0>7 THEN B1 = 7: IF B0 = 12 THEN B1 = 8 +5040 IF (ST$ = "B" OR ST$ = "C") AND B0<3 THEN B2 = 8 +5050 IF ST$ = "B" AND (B0 = 10 OR B0 = 11) THEN B1 = 7 +5060 IF ST$ = "B" AND B0 = 12 THEN B2 = 9 +5070 IF ST$ = "C" AND (B0 = 10 OR B0 = 11) THEN B2 = 8 +5080 IF ST$ = "C" AND B0 = 12 THEN B2 = 9 +5090 IF ST$ = "D" AND (B0 = 2 OR B0 = 11) THEN B2 = 8 +5100 IF ST$ = "D" AND B0 = 12 THEN B2 = 9 +5110 IF ST$ = "E" AND B0 = 12 THEN B2 = 8 +5120 IF ST$ = "X" AND B0 = 12 THEN B2 = 8 +5130 IF B1 = 6 THEN B$ = "E" +5140 IF B1 = 7 THEN B$ = "L" +5150 IF B2 = 8 THEN B$ = "M" +5160 IF B2 = 9 THEN B$ = "F" +5170 GOTO 6000 + +6000 REM TRADE CLASSIFICATIONS +6010 TC$ = "": IF AL$ = "KK" AND NK = 1 THEN TC$ = TC$ + "NK " +6030 IF AL$ = "HV" AND NH = 1 THEN TC$ = TC$ + "NH " +6040 IF AL$ = "HV" AND NH = 1 AND PO>7 AND (AM = 3 OR AM = 4 OR AM = 10 OR AM = 11 OR AM = 12) THEN TC$ = TC$ + "FA " +6045 IF PO>8 THEN TC$ = TC$ + "HI " +6047 IF PO<4 THEN TC$ = TC$ + "LO " +6050 IF (AM<3 OR AM = 4 OR AM = 7 OR AM = 9) AND PO>8 THEN TC$ = TC$ + "IN " +6055 IF (AM<2 AND HY>0) THEN TC$ = TC$ + "IC " +6060 IF PO<7 THEN TC$ = TC$ + "NI " +6065 IF AM>9 AND HY>0 THEN TC$ = TC$ + "FL " +6070 IF ( LEFT$ (AL$,1) = "A" OR AL$ = "HV" OR AL$ = "KK") AND (AM = 6 OR AM = 8) AND (PO>5 AND PO<9) THEN TC$ = TC$ + "RI ": GOTO 6120 +6080 IF LEFT$ (AL$,1) = "v" AND (AM = 6 OR AM = 8) AND (PO>5 AND PO<9) AND (GO<>7) THEN TC$ = TC$ + "RI ": GOTO 6120 +6090 IF AL$ = "DR" AND (AM = 6 OR AM = 8) AND (PO>5 AND PO<9) THEN TC$ = TC$ + "RI ": GOTO 6120 +6100 IF LEFT$ (AL$,1) = "Z" AND (TZ = 3 OR TZ = 4) AND (AM = 6 OR AM = 8) AND (PO>5 AND PO<9) THEN TC$ = TC$ + "RI ": GOTO 6120 +6110 IF (AM = 6 OR AM = 8) AND (PO>5 OR PO<9) AND (GO>3 AND GO<10) THEN TC$ = TC$ + "RI " +6120 IF (AM>1 AND AM<6) AND HY<4 THEN TC$ = TC$ + "PO " +6130 IF HY = 10 THEN TC$ = TC$ + "WA " +6140 IF HY = 0 AND AM>1 THEN TC$ = TC$ + "DE " +6150 IF SI = 0 THEN TC$ = TC$ + "AS " +6160 IF AM = 0 AND SI<>0 THEN TC$ = TC$ + "VA " +6170 IF AL$ = "KK" AND (SI = 7 OR SI = 8) AND (AM = 6 OR AM = 8) AND (HY>2 AND HY<6) THEN TC$ = TC$ + "ST " +6180 IF (AM>3 AND AM<10) AND (HY>3 AND HY<9) AND (PO>4 AND PO<8) THEN TC$ = TC$ + "AG " +6190 IF AM<4 AND HY<4 AND PO>5 THEN TC$ = TC$ + "NA " +6200 IF PO = 0 AND GO = 0 AND LA = 0 THEN TC$ = TC$ + "BA " +6210 TC$ = LEFT$ (TC$ + " ",15) + +6500 REM CREATE WORLD DATA STRING +6510 A$ = "": IF X<10 THEN A$ = "0" +6530 A$ = A$ + STR$ (X): IF Y<10 THEN A$ = A$ + "0" +6550 A$ = A$ + STR$ (Y) + " " +6560 IF HY<0 THEN HY = 0 +6570 IF AM<0 THEN AM = 0 +6580 A$ = A$ + ST$ + MID$ (HX$,SI + 1,1) + MID$ (HX$,AM + 1,1) + MID$ (HX$,HY + 1,1) +6590 A$ = A$ + MID$ (HX$,PO + 1,1) + MID$ (HX$,GO + 1,1) + MID$ (HX$,LA + 1,1) + "-" +6600 IF TL<0 THEN TL = 0 +6610 A$ = A$ + MID$ (HX$,TL + 1,1) + " ":A$ = A$ + B$ + " " +6625 IF PO = 0 THEN DR$ = "" +6630 IF DR$<>"" THEN A$ = A$ + DR$ + " " + LEFT$ (TC$,12): GOTO 6650 +6640 A$ = A$ + TC$ +6650 A$ = A$ + AL$ + " " +6660 IF TZ = 1 THEN A$ = A$ + "A " +6670 IF TZ = 2 THEN A$ = A$ + "R " +6680 IF TZ = 3 THEN A$ = A$ + "F " +6690 IF TZ = 4 THEN A$ = A$ + "U " +6700 IF TZ = 0 THEN A$ = A$ + " " +6710 IF GG = 0 THEN A$ = A$ + " " +6720 IF GG = 1 THEN A$ = A$ + "G " + +7000 REM SAVE TO DISK +7010 R = R + 1 +7020 PRINT CHR$ (4);"WRITE SECTOR, R";R +7030 PRINT A$ +7040 PRINT CHR$ (4) +7040 PRINT A$ +7070 NEXT Y: NEXT X + +7090 REM SAVE FILE LENGTH +7100 PRINT CHR$ (4);"WRITE SECTOR, R0" +7110 PRINT R +7120 PRINT CHR$ (4);"CLOSE" + +7130 REM SAVE FILE PARAMETERS +7140 INPUT "NAME THIS FILE? > ";FI$ +7150 PRINT CHR$ (4);"RENAME SECTOR,";FI$ +7160 PRINT CHR$ (4);"OPEN ";FI$;"@" +7170 PRINT CHR$ (4);"WRITE ";FI$;"@" +7180 PRINT 9: PRINT R: PRINT 49 +7190 PRINT "HEX ": PRINT 4 +7200 PRINT "UPP ": PRINT 9 +7210 PRINT "BASES ": PRINT 1 +7220 PRINT "TRADE CLA ": PRINT 14 +7280 PRINT "ALLEG ": PRINT 2 +7290 PRINT "TRAVEL ZO ": PRINT 1 +7300 PRINT "GAS GIANT ": PRINT 1 +7310 PRINT "TRADEWRLD ": PRINT 1 +7320 PRINT "EXPLORED? ": PRINT 1 +7390 PRINT CHR$ (4);"CLOSE" +7400 END diff --git a/samples/sample.sierpinski.txt b/samples/sample.sierpinski.txt new file mode 100644 index 0000000..a6efece --- /dev/null +++ b/samples/sample.sierpinski.txt @@ -0,0 +1,24 @@ +10 TEXT : HOME +20 PRINT "Sierpinski triangle using random number generation" +30 PRINT "Press any key to continue" +40 GET A$ +100 HGR : HCOLOR=3 : HOME +110 REM set up three points to form a triangle +120 DIM x(3), y(3) +130 x(0) = 0 : y(0) = 160 +140 x(1) = 90 : y(1) = 0 +150 x(2) = 180 : y(2) = 160 +160 REM plot the vertices of the triangle +170 FOR i= 0 to 2 +180 HPLOT x(i), y(i) +190 NEXT i +200 REM pick a random starting point +210 x = int(RND(1)*180) : y = int(RND(1)*150) +220 hplot x,y +230 FOR i = 1 to 2000 +240 REM randomly pick one of the triangle vertices +250 v = int(rnd(1)*3) +260 REM move the point half way to the triangle vertex +270 x = (x + x(v)) / 2 : y = (y + y(v)) / 2 +280 HPLOT x,y +290 NEXT diff --git a/samples/sample.squiggle.txt b/samples/sample.squiggle.txt new file mode 100644 index 0000000..4d46ecb --- /dev/null +++ b/samples/sample.squiggle.txt @@ -0,0 +1,35 @@ +5 REM Squiggle by Gregg Buntin +10 TEXT +20 HOME +30 INPUT "Enter a number from 1 to 8:";N +40 IF N > 0 AND N < 8 THEN F = 128 +50 E = 0 +60 K = 4 ^ N +70 FOR X = 1 TO N +80 U = F +90 F = - E / 2 +100 E = U / 2 +110 NEXT +120 HGR +130 HCOLOR= 3 +140 X = 80 +150 Y = 70 +160 HPLOT X,Y +170 FOR M = 1 TO K +180 Z = M +190 X = X + F +200 Y = Y + E +210 HPLOT TO X,Y +220 FOR A = 0 TO 1 +230 Z = Z / 2 +240 Q = INT (Z) +250 A = Z - Q +260 NEXT +270 A = (Q / 2 = INT (Q / 2)) * 2 - 1 +280 U = F +290 F = A * E +300 E = - A * U +310 NEXT +320 GOTO 10 + + diff --git a/samples/sample.steve.txt b/samples/sample.steve.txt new file mode 100644 index 0000000..827dea4 --- /dev/null +++ b/samples/sample.steve.txt @@ -0,0 +1,71 @@ +1 REM In honor of Steve Jobs passing I went +2 REM back to my Apple BASIC roots. I learned +3 REM on an Apple IIe in my library and over +4 REM the summer at summer school. +5 REM It was then that I learned I wasnt a coder +6 REM and still am not today but it was my start +7 REM in learning technology outside of the slide +8 REM and film projectors. +9 REM +10 REM If I have more time maybe I'll bust out +11 REM something more exciting. +12 +13 REM You can run this program via the URL below +14 REM http://www.calormen.com/Applesoft/. +16 REM +18 HOME +19 HGR +20 HCOLOR=2 +25 REM R +30 HPLOT 90,70 TO 90,0 TO 125,0 TO 125,35 TO 90,35 TO 125,70 +100 REM I +110 HPLOT 130,0 TO 165,0 +120 HPLOT 130,70 TO 165,70 +130 HPLOT 147,0 TO 147,70 +150 REM P +160 HPLOT 170,70 TO 170,0 TO 205,0 TO 205,35 TO 170,35 +200 REM S +210 HPLOT 23,82 TO 0,82 TO 0,94 TO 23,94 TO 23,106 TO 0,106 +300 REM T +310 HPLOT 27,82 TO 51,82 +320 HPLOT 39,82 TO 39,106 +350 REM E +360 HPLOT 79,82 TO 55,82 TO 55,106 TO 79,106 +380 HPLOT 55,94 TO 67,94 +400 REM V +410 HPLOT 83,82 TO 95,106 TO 107,82 +450 REM E +460 HPLOT 134,82 TO 110,82 TO 110,106 TO 134,106 +480 HPLOT 110,94 TO 122,94 +500 REM J +510 HPLOT 168,82 TO 190,82 +520 HPLOT 178,82 TO 178,106 TO 168,106 TO 168,98 +550 REM O +560 HPLOT 194,82 TO 218,82 TO 218,106 TO 194,106 TO 194,82 +600 REM B +610 HPLOT 222,82 TO 240,82 TO 246,84 TO 246,104 TO 240,106 TO 222,106 TO 222,82 +650 HPLOT 222,94 TO 246,94 +700 REM S +710 HPLOT 274,82 TO 250,82 TO 250,94 TO 274,94 TO 274,106 TO 250,106 +800 REM 1 +810 HPLOT 2,120 TO 14,116 TO 14,140 +820 HPLOT 2,140 TO 25,140 +850 REM 9 +860 HPLOT 57,116 TO 33,116 TO 33,128 TO 57,128 +890 HPLOT 57,116 TO 57,140 +900 REM 5 +910 HPLOT 89,116 TO 65,116 TO 65,128 TO 85,128 TO 89,132 TO 89,138 TO 87,140 TO 65,140 +1000 REM 5 +1010 HPLOT 121,116 TO 97,116 TO 97,128 TO 117,128 TO 121,132 TO 121,138 TO 119,140 TO 97,140 +1070 REM - +1080 HPLOT 131,128 TO 151,128 +1100 REM 2 +1110 HPLOT 161,116 TO 185,116 TO 185,128 TO 161,128 TO 161,140 TO 185,140 +1200 REM 0 +1210 HPLOT 217,116 TO 193,116 TO 193,140 TO 217,140 TO 217,116 +1250 REM 1 +1260 HPLOT 235,140 TO 235,116 TO 223,120 +1270 HPLOT 223,140 TO 247,140 +1300 REM 1 +1310 HPLOT 265,140 TO 265,116 TO 253,120 +1320 HPLOT 253,140 TO 277,140 \ No newline at end of file diff --git a/samples/sample.stringart.txt b/samples/sample.stringart.txt new file mode 100644 index 0000000..b85bb17 --- /dev/null +++ b/samples/sample.stringart.txt @@ -0,0 +1,11 @@ +10 HGR +20 hcolor=1 +30 y=191 +40 for x=1 to 191 step 5 +50 c=c+1 +60 if c=>6 then c=1 +70 hcolor=c +80 hplot x,1 to 1,y +90 y=y-5 +100 next x +110 goto 30 diff --git a/samples/sample.unittests.txt b/samples/sample.unittests.txt new file mode 100644 index 0000000..b1252c8 --- /dev/null +++ b/samples/sample.unittests.txt @@ -0,0 +1,812 @@ + +0 GOTO 100 + +1 REM LET T$ = "test desc" : LET S = 0 OR 1 : GOSUB 1 +2 IF S THEN PRINT "."; +3 IF NOT S THEN INVERSE : PRINT " Test ";T$;" Failed "; : NORMAL : PRINT ""; : F = F + 1 +4 TE = TE + 1 : TS = TS + (NOT NOT S) : S = 0 : RETURN + +100 REM Pre-test for CLEAR +110 A = 1 : A$ = "a" : A(1) = 2 : A$(1) = "b" : CLEAR + +200 REM Feature Detection +210 LR = 0 : ONERR GOTO 220 : GR : LR = 1 +220 HR = 0 : ONERR GOTO 240 : HGR : HR = 1 +230 PD = 0 : ONERR GOTO 240 : X = PDL(0) : PD = 1 +240 POKE 216,0 + +300 PR#3 : TEXT : HOME : PRINT "Unit Tests" + +1000 PRINT : PRINT "Variable Control "; + +1010 REM Ensure CLEAR in line 110 occurred +: T$ = "CLEAR" +: S = ( A = 0 ) : GOSUB 1 +: S = ( A$ = "" ) : GOSUB 1 +: S = ( A(1) = 0 ) : GOSUB 1 +: S = ( A$(1) = "" ) : GOSUB 1 + +1020 T$ = "Implicit LET" +: A = 123 : S = ( A = 123 ) : GOSUB 1 +: A$ = "abc" : S = ( A$ = "abc" ) : GOSUB 1 +: A(1) = 234: S = ( A(1) = 234 ) : GOSUB 1 +: A$(1) = "bcd" : S = ( A$(1) = "bcd" ) : GOSUB 1 + +1030 T$ = "Explicit LET" +: LET A = 123 : S = ( A = 123 ) : GOSUB 1 +: LET A$ = "abc" : S = ( A$ = "abc" ) : GOSUB 1 +: LET A(1) = 234 : S = ( A(1) = 234 ) : GOSUB 1 +: LET A$(1) = "bcd" : S = ( A$(1) = "bcd" ) : GOSUB 1 + +1040 T$ = "DIM" +: DIM AR(12) +: FOR I = 0 TO 12 : AR(I) = I : NEXT +: T = 0 : U = 0 +: FOR I = 0 TO 12 : T = T + I : U = U + AR(I) : NEXT +: S = (T = U) : GOSUB 1 + +1050 T$ = "DEF FN" +: DEF FN FA(X) = X+X : S = (FN FA(3) = 6) : GOSUB 1 +: DEF FN FB(X) = X*X : S = (FN FB(3) = 9) : GOSUB 1 + + +2000 PRINT : PRINT "Flow Control "; + +2010 T$ = "GOTO" : T = 1 : GOTO 2017 : T = T + 1 +2015 T = T + 1 : GOTO 2019 : T = T + 1 +2017 T = T + 1 : GOTO 2015 +2018 T = T + 1 +2019 S = (T=3) : GOSUB 1 + +2020 T$ = "GOSUB/RETURN" : T = 1 : GOSUB 2025 : GOTO 2029 +2025 T = T + 1 : RETURN +2029 S = (T=2) : GOSUB 1 + +2030 T$ = "ON GOTO" : T = 1 : ON 2 GOTO 2031, 2032, 2033 +2031 T = T + 1 +2032 T = T + 1 +2033 T = T + 1 +2039 S = (T=3) : GOSUB 1 + +2040 T$ = "ON GOSUB" : T = 1 : ON 2 GOSUB 2041, 2042, 2043 : GOTO 2049 +2041 T = T + 1 : RETURN +2042 T = T + 2 : RETURN +2043 T = T + 3 : RETURN +2049 S = (T=3) : GOSUB 1 + +2050 T$ = "POP" : T = 1 : GOSUB 2055 : T = T + 1 : GOTO 2059 +2055 T = T + 1 : GOSUB 2056 : T = T + 5 +2056 POP : T = T + 1 : RETURN +2059 S = (T=4) : GOSUB 1 + +2060 T$ = "FOR" +: T = 0 : FOR I = 1 TO 10 : T = T + I : NEXT +: S = (T = 55) : GOSUB 1 +2061 T$ = "FOR STEP" +: T = 0 : FOR I = 1 TO 10 STEP 2 : T = T + I : NEXT +: S = (T = 25) : GOSUB 1 +2062 T$ = "FOR STEP" +: T = 0 : FOR I = 10 TO 1 STEP -1 : T = T + I : NEXT +: S = (T = 55) : GOSUB 1 +2063 T$ = "FOR STEP" +: T = 0 : FOR I = 10 TO 1 : T = T + I : NEXT +: S = (T = 10) : GOSUB 1 + +2070 T$ = "NEXT" +: T = 0 : FOR I = 1 TO 10 : FOR J = 1 TO 10 : FOR K = 1 TO 10 : T = T + 1 : NEXT J, I +: S = (T=100) : GOSUB 1 + +2080 T$ = "IF THEN" +: T = 1 : IF 0 THEN T = 2 +2081 S = (T=1) : GOSUB 1 +: T = 1 : IF 1 THEN T = 2 : T = 3 +2082 S = (T=3) : GOSUB 1 + +2090 T$ = "IF GOTO" +: T = 1 : IF 0 GOTO 2092 : T = 2 +2091 T = 3 +2092 S = (T=3) : GOSUB 1 +: T = 1 : IF 1 GOTO 2094 : T = 2 +2093 T = 3 +2094 S = (T=1) : GOSUB 1 + +2100 T$ = "Empty String is False" +: T = 1 : IF "" THEN T = 2 +2101 S = (T=1) : GOSUB 1 + +2110 T$ = "Non-Empty String is True" +: T = 1 : IF "abc" THEN T = 2 +2111 S = (T=2) : GOSUB 1 + + +3000 PRINT : PRINT "Error Handling "; + +3010 T$ = "ONERR GOTO" +: T = 1 : ONERR GOTO 3015 : T = 1 / 0 +3011 T = 2 +3015 S = (T=1) : GOSUB 1 + +3020 T$ = "RESUME" +: T = 0 : ONERR GOTO 3025 : T = 1 / T : GOTO 3029 +3025 T = 1 : RESUME +3029 S = (T=1) : GOSUB 1 + +3040 T$ = "RETURN FROM LOOP" +: T = 1 : ONERR GOTO 3046 +: GOSUB 3045 +: GOTO 3048 +3045 FOR I = 1 TO 10 : RETURN +3046 T = 2 : REM ONERR goes here +3048 S = (T=1) : GOSUB 1 + +3100 T$ = "NEXT WITHOUT FOR" +: T = 1 : ONERR GOTO 3101 +: NEXT +: T = 2 +3101 S = (T=1) AND (PEEK(222)=0) : GOSUB 1 + +3110 T$ = "SYNTAX ERROR" : REM Compile time only, can't test! + +3120 T$ = "RETURN WITHOUT GOSUB" +: T = 1 : ONERR GOTO 3121 +: RETURN +: T = 2 +3121 S = (T=1) AND (PEEK(222)=22) : GOSUB 1 + +3130 T$ = "OUT OF DATA" +: T = 1 : ONERR GOTO 3131 +: FOR A = 1 TO 1000 : READ A$ : NEXT +: T = 2 +3131 S = (T=1) AND (PEEK(222)=42) : GOSUB 1 + +3140 T$ = "ILLEGAL QUANTITY" +: T = 1 : ONERR GOTO 3141 +: A% = 32768 +: T = 2 +3141 S = (T=1) AND (PEEK(222)=53) : GOSUB 1 + +3145 T$ = "ILLEGAL QUANTITY" +: T = 1 : ONERR GOTO 3146 +: A = ASC("") +: T = 2 +3146 S = (T=1) AND (PEEK(222)=53) : GOSUB 1 + +3150 T$ = "OVERFLOW" : +: T = 1 : ONERR GOTO 3151 +: A = 256^256^256 +: T = 2 +3151 S = (T=1) AND (PEEK(222)=69) : GOSUB 1 + +3160 T$ = "OUT OF MEMORY" : REM Not consistent enough across browsers +: REM T = 1 : ONERR GOTO 3161 +: REM A$ = "x" +: REM FOR I = 0 TO 1 STEP 0 : A$ = A$ + A$ : NEXT +: REM T = 2 +3161 REM S = (T=1) AND (PEEK(222)=77) : GOSUB 1 + +3170 T$ = "UNDEFINED STATEMENT" : +: T = 1 : ONERR GOTO 3171 +: GOTO 3172 +: T = 2 +3171 S = (T=1) AND (PEEK(222)=90) : GOSUB 1 + +3180 T$ = "BAD SUBSCRIPT" : +: T = 1 : ONERR GOTO 3181 +: DIM BS(3) : BS(4) = 123 +: T = 2 +3181 S = (T=1) AND (PEEK(222)=107) : GOSUB 1 + +3190 T$ = "REDIMENSION ARRAY" : +: T = 1 : ONERR GOTO 3191 +: DIM RA(3) : DIM RA(3) +: T = 2 +3191 S = (T=1) AND (PEEK(222)=120) : GOSUB 1 + +3200 T$ = "DIVISION BY ZERO" : +: T = 1 : ONERR GOTO 3201 +: A = 1 / 0 +: T = 2 +3201 S = (T=1) AND (PEEK(222)=133) : GOSUB 1 + +3210 T$ = "TYPE MISMATCH" : +: T = 1 : ONERR GOTO 3211 +: RESTORE : FOR I = 1 TO 1000 : READ A : NEXT +: T = 2 +3211 S = (T=1) AND (PEEK(222)=163) : GOSUB 1 + +3215 T$ = "TYPE MISMATCH" : +: T = 1 : ONERR GOTO 3216 +: RESTORE : FOR I = 1 TO 1000 : READ A% : NEXT +: T = 2 +3216 S = (T=1) AND (PEEK(222)=163) : GOSUB 1 + +3220 T$ = "STRING TOO LONG" : REM Strings are "infinite", can't test + +3230 T$ = "FORMULA TOO COMPLEX" +: REM T = 1 : ONERR GOTO 3231 +: REM DEF FN FC(x) = FN FC(x) + 1 : X = FN FC(0) +: REM T = 2 +3231 REM S = (T=1) AND (PEEK(222)=191): GOSUB 1 + +3240 T$ = "UNDEFINED FUNCTION" : +: T = 1 : ONERR GOTO 3241 +: X = FN UF(0) +: T = 2 +3241 S = (T=1) AND (PEEK(222)=224) : GOSUB 1 + +3250 T$ = "RE-ENTER" : REM Can't test until input can be synthesized + +3260 T$ = "BREAK" : +: T = 1 : ONERR GOTO 3261 +: STOP +: T = 2 +3261 S = (T=1) AND (PEEK(222)=255) : GOSUB 1 + + + +3999 POKE 216,0 : REM Disable ONERR handler + + + +4000 PRINT : PRINT "Input/Output "; +: PRINT "UNIT TESTS NOT FULLY IMPLEMENTED "; + +4010 REM ********************************************** +4010 REM Do I/O as a follow-on module and introduce +4010 REM a non-standard screen-scraping function +4010 REM ********************************************** + +4010 REM ********************************************** +4010 REM Test TRACE/NOTRACE as part of I/O functions +4010 REM ********************************************** + + + +4100 T$ = "HTAB" : +: SX = PEEK(36) : SY = PEEK(37) +: HTAB 10 : T = PEEK(36) +: POKE 36, SX : POKE 37, SY +: S = (T = 10 - 1) : GOSUB 1 + +4110 T$ = "VTAB" : +: SX = PEEK(36) : SY = PEEK(37) +: VTAB 10 : T = PEEK(37) +: POKE 36, SX : POKE 37, SY +: S = (T = 10 - 1) : GOSUB 1 + +4120 T$ = "Comma Operator" : +: SX = PEEK(36) : SY = PEEK(37) +: VTAB 23 : HTAB 1 : PRINT 1, : T = PEEK(36) +: VTAB 23 : HTAB 1 : PRINT SPC(40); +: POKE 36, SX : POKE 37, SY +: S = (T = 16) : GOSUB 1 + +4130 T$ = "Semicolon Operator" : +: SX = PEEK(36) : SY = PEEK(37) +: VTAB 23 : HTAB 1 : PRINT "abc"; : T = PEEK(36) +: VTAB 23 : HTAB 1 : PRINT SPC(40); +: POKE 36, SX : POKE 37, SY +: S = (T = 3) : GOSUB 1 + +4140 T$ = "SPC Operator" : +: SX = PEEK(36) : SY = PEEK(37) +: VTAB 23 : HTAB 1 : PRINT "abc";SPC(10); : T = PEEK(36) +: VTAB 23 : HTAB 1 : PRINT SPC(40); +: POKE 36, SX : POKE 37, SY +: S = (T = 13) : GOSUB 1 + +4150 T$ = "TAB Operator" : +: SX = PEEK(36) : SY = PEEK(37) +: VTAB 23 : HTAB 1 : PRINT "abc";TAB(10); : T = PEEK(36) +: VTAB 23 : HTAB 1 : PRINT SPC(40); +: POKE 36, SX : POKE 37, SY +: S = (T = 9) : GOSUB 1 + + + + +5000 PRINT : PRINT "Miscellaneous "; + +5010 T$ = "REM" : T = 1 : REM T = 2 : T = 3 +5011 S = (T=1) : GOSUB 1 + + + +6000 PRINT : PRINT "Inline Data "; + +6010 DATA 1,2,3 +6011 DATA "A","B","C" + +6010 T$ = "READ" +: RESTORE +: READ T : S = (T=1) : GOSUB 1 +: READ T,U : S = (T=2 AND U=3) : GOSUB 1 +: READ A$ : S = (A$="A") : GOSUB 1 +: READ A$,B$ : S = (A$="B" AND B$="C") : GOSUB 1 + +6020 T$ = "RESTORE" : RESTORE +: READ T : S = (T=1) : GOSUB 1 +: READ T,U : S = (T=2 AND U=3) : GOSUB 1 +: READ A$ : S = (A$="A") : GOSUB 1 +: READ A$,B$ : S = (A$="B" AND B$="C") : GOSUB 1 + + +7000 PRINT : PRINT "Lo-Res Graphics "; +7001 IF NOT LR THEN PRINT "" : GOTO 8000 + +7010 REM ************************************************************ +7010 REM Test GR as part of I/O (sets cursor to window bottom) +7010 REM ************************************************************ + +7010 POKE 49232,0 : POKE 49234,0 : POKE 49238,0 + +7020 T$ = "COLOR=" +: T = 0 : U = 0 : FOR I = 0 TO 15 : COLOR= I : PLOT 0,0 : T = T + I : U = U + SCRN(0,0) : NEXT +: S = (T=U) : GOSUB 1 + +7030 T$ = "PLOT" +: COLOR= 5 : PLOT 0,0 : PLOT 39,0 : PLOT 0,47 : PLOT 39,47 +: COLOR= 6 : PLOT 0,0 : PLOT 39,0 : PLOT 0,47 : PLOT 39,47 +: S = (SCRN(0,0)=6 AND SCRN(39,0)=6 AND SCRN(0,47)=6 AND SCRN(39,47)=6) : GOSUB 1 + +7040 T$ = "HLIN" +: COLOR= 0 : FOR Y = 0 TO 5: FOR X = 0 TO 10 : PLOT X,Y : NEXT : NEXT +: FOR I = 1 TO 5 : COLOR= I : HLIN I,10-I AT I : NEXT +: T = 0 : FOR Y = 0 TO 5: FOR X = 0 TO 10 : T = T + SCRN(X,Y) : NEXT : NEXT +: S = (T=55) : GOSUB 1 + +7050 T$ = "VLIN" +: COLOR= 0 : FOR Y = 0 TO 10: FOR X = 0 TO 5 : PLOT X,Y : NEXT : NEXT +: FOR I = 1 TO 5 : COLOR= I : VLIN I,10-I AT I : NEXT +: T = 0 : FOR Y = 0 TO 10: FOR X = 0 TO 5 : T = T + SCRN(X,Y) : NEXT : NEXT +: S = (T=55) : GOSUB 1 + +: COLOR= 6 : PLOT 0,0 : PLOT 39,0 : PLOT 0,47 : PLOT 39,47 +: S = (SCRN(0,0)=6 AND SCRN(39,0)=6 AND SCRN(0,47)=6 AND SCRN(39,47)=6) : GOSUB 1 + +7900 REM Something memorable +7910 FOR I = 0 TO 15 +: COLOR= I +: HLIN I, 39-I AT I +: HLIN I, 39-I AT 39 - I +: VLIN I, 39-I AT I +: VLIN I, 39-I AT 39 - I +: NEXT + +7999 TEXT +8000 PRINT : PRINT "Hi-Res Graphics "; +8001 IF NOT HR THEN PRINT "" : GOTO 9000 + +8020 T$ = "HCOLOR=" +: HGR +: T = 0 : U = 0 : FOR I = 0 TO 7 : HCOLOR= I : HPLOT 0,0 : T = T + I : U = U + HSCRN(0,0) : NEXT +: S = (T=U) : GOSUB 1 + +8030 T$ = "HPLOT" +: HGR +: HCOLOR= 5 : HPLOT 0,0 : HPLOT 39,0 : HPLOT 0,47 : HPLOT 39,47 +: HCOLOR= 6 : HPLOT 0,0 : HPLOT 39,0 : HPLOT 0,47 : HPLOT 39,47 +: S = (HSCRN(0,0)=6 AND HSCRN(39,0)=6 AND HSCRN(0,47)=6 AND HSCRN(39,47)=6) : GOSUB 1 + +8040 T$ = "HPLOT x1,y1 TO x2,y2" +: HGR +: FOR Y = 0 TO 7: HCOLOR= Y : HPLOT 0,Y TO 7,Y: NEXT +: T = 0 : U = 0 : FOR I = 0 TO 7 : T = T + HSCRN(I,I) : U = U + I : NEXT +: S = (T=U) : GOSUB 1 + +8050 T$ = "HPLOT TO x2,y2" +: HGR +: FOR X = 0 TO 7: HCOLOR= X : HPLOT X*2,0 : HPLOT TO X*2,7 : NEXT +: T = 0 : U = 0 : FOR I = 0 TO 7 : T = T + HSCRN(I*2,I) : U = U + I : NEXT +: S = (T=U) : GOSUB 1 + +8100 REM Visual Check + +8110 HGR + +8120 T$ = "HCOLOR=" +: T = 0 : U = 0 : FOR I = 0 TO 7 : HCOLOR= I : HPLOT 0,0 : T = T + I : NEXT + +8130 T$ = "HPLOT x,y" +: HCOLOR= 3 : HPLOT 0,0 : HPLOT 279,0 : HPLOT 0,191 : HPLOT 279,191 + +8140 T$ = "HPLOT TO x,y" +: HCOLOR= 2 : HPLOT 10,10 : HPLOT TO 269,10 : HPLOT TO 269,181 : HPLOT TO 10,181 : HPLOT TO 10,10 + +8150 T$ = "HPLOT x,y TO x,y" +: HCOLOR= 1 : HPLOT 20,20 TO 259,20 : HPLOT 259,20 TO 259,171 : HPLOT 259,171 TO 20,171 : HPLOT 20,171 TO 20,20 + +8160 T$ = "HPLOT x,y TO x,y TO x,y" +: HCOLOR= 5 : HPLOT 30,30 TO 249,30 TO 249,161 TO 30,161 TO 30,30 + +8200 HGR : REM Something visually memorable + +8210 W = 279 : H = 159 +8220 FOR I = 0 TO 1 STEP 0.05 +8230 HCOLOR= 1 : HPLOT 0,H * I TO W* (1-I),0 +8231 HCOLOR= 2 : HPLOT 0,H * (1-I) TO W* (1-I),H +8232 HCOLOR= 5 : HPLOT W,H * I TO W * I,0 +8233 HCOLOR= 6 : HPLOT W,H * (1-I) TO W * I,H +8234 NEXT + +8999 TEXT + + + +9000 PRINT : PRINT "POKE Compatibility Shims "; +: PRINT "UNIT TESTS NOT YET IMPLEMENTED "; +9001 POKE 49168,0 : POKE -16368,0 : REM Clear kbd strobe +9002 POKE 49200,0 : POKE -16336,0 : REM Toggle speaker +9003 POKE 49232,0 : POKE -16304,0 : REM Graphics mode +9004 POKE 49234,0 : POKE -16302,0 : REM Full graphics mode +9005 POKE 49235,0 : POKE -16301,0 : REM Split screen mode +9006 POKE 49238,0 : POKE -16298,0 : REM Lores mode +9007 POKE 49239,0 : POKE -16297,0 : REM Hires mode +9008 POKE 49233,0 : POKE -16303,0 : REM Text mode +9009 SPEED= 0 : SPEED= 255 : REM SPEED= (no-op) + +10000 PRINT : PRINT "Numeric Functions "; +10001 DEF FN E(X) = ABS(X) < 0.001 : REM Within-Epsilon + +10010 T$ = "ABS()" +: S = (ABS(1) = 1) : GOSUB 1 +: S = (ABS(-1) = 1) : GOSUB 1 +: S = (ABS(0) = 0) : GOSUB 1 + +10020 T$ = "ATN()" +: S = FN E(ATN(0) - 0.000) : GOSUB 1 +: S = FN E(ATN(1) - 0.785) : GOSUB 1 +: S = FN E(ATN(2) - 1.107) : GOSUB 1 + +10030 T$ = "COS()" +: S = FN E(COS(0) - 1.000) : GOSUB 1 +: S = FN E(COS(1) - 0.540) : GOSUB 1 +: S = FN E(COS(2) - -0.416) : GOSUB 1 + +10040 T$ = "EXP()" +: S = FN E(EXP(0) - 1.000) : GOSUB 1 +: S = FN E(EXP(1) - 2.718) : GOSUB 1 +: S = FN E(EXP(2) - 7.389) : GOSUB 1 + +10050 T$ = "INT()" +: S = (INT(1) = 1) : GOSUB 1 +: S = (INT(1.5) = 1) : GOSUB 1 +: S = (INT(-1.5) = -2) : GOSUB 1 + +10060 T$ = "LOG()" +: S = FN E(LOG(1) - 0.000) : GOSUB 1 +: S = FN E(LOG(2) - 0.693) : GOSUB 1 +: S = FN E(LOG(3) - 1.098) : GOSUB 1 + +10070 T$ = "RND()" +: T = RND(1) : S = (FN E(T - RND(0))) : GOSUB 1 +: T = RND(-1) : T = RND(1) : U = RND(-1) : U = RND(1) : S = (FN E(T - U)) : GOSUB 1 + +10080 T$ = "SGN()" +: S = (SGN(-123)=-1): GOSUB 1 +: S = (SGN( 0)= 0): GOSUB 1 +: S = (SGN( 123)= 1): GOSUB 1 + +10090 T$ = "SIN()" +: S = FN E(SIN(0) - 0.000) : GOSUB 1 +: S = FN E(SIN(1) - 0.841) : GOSUB 1 +: S = FN E(SIN(2) - 0.909) : GOSUB 1 + +10100 T$ = "SQR()" +: S = FN E(SQR(0) - 0.000) : GOSUB 1 +: S = FN E(SQR(1) - 1.000) : GOSUB 1 +: S = FN E(SQR(2) - 1.414) : GOSUB 1 + +10110 T$ = "TAN()" +: S = FN E(TAN(0) - 0.000) : GOSUB 1 +: S = FN E(TAN(1) - 1.557) : GOSUB 1 +: S = FN E(TAN(2) --2.185) : GOSUB 1 + + +11000 PRINT : PRINT "String Functions "; + +11010 T$ = "LEN()" +: S = (LEN("ABC") = 3) : GOSUB 1 +: S = (LEN("") = 0) : GOSUB 1 + +11020 T$ = "LEFT$()" +: S = (LEFT$("ABC",0) = "") : GOSUB 1 +: S = (LEFT$("ABC",2) = "AB") : GOSUB 1 +: S = (LEFT$("ABC",4) = "ABC") : GOSUB 1 + +11030 T$ = "MID$()" +: S = (MID$("ABCD",2,2) = "BC") : GOSUB 1 +: S = (MID$("ABCD",3) = "CD") : GOSUB 1 +: S = (MID$("ABCD",4,3) = "D") : GOSUB 1 + +11040 T$ = "RIGHT$()" +: S = (RIGHT$("ABC",0) = "") : GOSUB 1 +: S = (RIGHT$("ABC",2) = "BC") : GOSUB 1 +: S = (RIGHT$("ABC",4) = "ABC") : GOSUB 1 + + +12000 PRINT : PRINT "Type Conversion Functions "; + +12010 T$ = "ASC()" +: S = (ASC(" ") = 32) : GOSUB 1 +: S = (ASC("A") = 65) : GOSUB 1 +: S = (ASC("z") = 122) : GOSUB 1 +: S = (ASC(CHR$(4)) = 4) : GOSUB 1 + +12020 T$ = "CHR$()" +: S = (CHR$(32) = " ") : GOSUB 1 +: S = (CHR$(65) = "A") : GOSUB 1 +: S = (CHR$(122) = "z") : GOSUB 1 + +12030 T$ = "STR$()" +: S = (STR$(-1) = "-1") : GOSUB 1 +: S = (STR$(1.5) = "1.5") : GOSUB 1 +: S = (STR$(3.1415) = "3.1415") : GOSUB 1 +: S = (VAL(STR$(3.1415)) = 3.1415) : GOSUB 1 + +12040 T$ = "VAL()" +: S = (VAL("-1") = -1) : GOSUB 1 +: S = (VAL("1.5") = 1.5) : GOSUB 1 +: S = (VAL("3.1415") = 3.1415) : GOSUB 1 + + +13000 PRINT : PRINT "System Interaction Functions "; + +13010 T$ = "FRE()" +: S = (FRE(0) OR 1) : GOSUB 1 + +13020 IF NOT PD THEN PRINT ""; : GOTO 13030 +13021 T$ = "PDL()" +: T = PDL(0) : S = (0 <= T) AND (T < 256) : GOSUB 1 + +13030 T$ = "POS()" +: T = POS(0) : HTAB 1 : S = (POS(0) = 0) : HTAB T + 1 : GOSUB 1 + +13040 IF NOT LR THEN PRINT ""; : GOTO 13050 +13041 T$ = "SCRN()" +: T = 0 : FOR I = 0 TO 15 : COLOR= I : PLOT I,I : T = T + I : NEXT +: U = 0 : FOR I = 0 TO 15 : U = U + SCRN(I,I) : NEXT +: S = (T=U) : GOSUB 1 + +13050 IF NOT HR THEN PRINT ""; : GOTO 13060 +13051 T$ = "HSCRN()" +: T = 0 : FOR I = 0 TO 7 : HCOLOR= I : HPLOT I,I : T = T + I : NEXT +: U = 0 : FOR I = 0 TO 7 : U = U + HSCRN(I,I) : NEXT +: S = (T=U) : GOSUB 1 + +13060 REM (goto target) + +14000 PRINT : PRINT "User Defined Functions "; + +14010 T$ = "FN A()" +: DEF FN A(X) = X + X : S = (FN A(3) = 6) : GOSUB 1 +: DEF FN A(X) = X * X : S = (FN A(3) = 9) : GOSUB 1 + +14020 T$ = "FN A$() [language extension]" +: DEF FN A$(X$) = X$ + X$ : S = (FN A$("ABC") = "ABCABC") : GOSUB 1 + +15000 PRINT : PRINT "PEEK Compatibility Shims "; +: PRINT "UNIT TESTS NOT YET IMPLEMENTED "; +15001 X = PEEK(49152) : X = PEEK(-16384) : REM Read keyboard +15002 X = PEEK(49168) : X = PEEK(-16368) : REM Clear keyboard strobe +15003 X = PEEK(49200) : X = PEEK(-16336) : REM Toggle speaker (no-op) +15004 X = PEEK(49248) : X = PEEK(-16288) : REM Read paddle button 3 +15005 X = PEEK(49249) : X = PEEK(-16287) : REM Read paddle button 0 +15006 X = PEEK(49250) : X = PEEK(-16286) : REM Read paddle button 1 +15007 X = PEEK(49251) : X = PEEK(-16285) : REM Read paddle button 2 +15008 X = PEEK(78) + 256 * PEEK(79) : REM Entropy generator + +15010 REM ********************************************** +15010 REM Do as part of I/O follow-on module +15010 REM ********************************************** + + +16000 PRINT : PRINT "Operators "; + +16010 T$ = "=" +: S = (1 = 1.0) : GOSUB 1 +: S = ("ABC" = "ABC") : GOSUB 1 + +16020 T$ = "<" +: S = (1 < 2) : GOSUB 1 +: S = ("A" < "B") : GOSUB 1 + +16030 T$ = ">" +: S = (2 > 1) : GOSUB 1 +: S = ("B" > "A") : GOSUB 1 + +16040 T$ = "<=" +: S = (1 <= 1) : GOSUB 1 +: S = (1 <= 2) : GOSUB 1 +: S = (1 < = 1) : GOSUB 1 +: S = (1 < = 2) : GOSUB 1 +: S = ("A" <= "A") : GOSUB 1 +: S = ("A" <= "B") : GOSUB 1 +: S = ("A" < = "A") : GOSUB 1 +: S = ("A" < = "B") : GOSUB 1 +16041 T$ = "=<" +: S = (1 =< 1) : GOSUB 1 +: S = (1 =< 2) : GOSUB 1 +: S = (1 = < 1) : GOSUB 1 +: S = (1 = < 2) : GOSUB 1 +: S = ("A" =< "A") : GOSUB 1 +: S = ("A" =< "B") : GOSUB 1 +: S = ("A" = < "A") : GOSUB 1 +: S = ("A" = < "B") : GOSUB 1 + +16050 T$ = ">=" +: S = (1 >= 1) : GOSUB 1 +: S = (2 >= 1) : GOSUB 1 +: S = (1 > = 1) : GOSUB 1 +: S = (2 > = 1) : GOSUB 1 +: S = ("B" >= "A") : GOSUB 1 +: S = ("B" >= "B") : GOSUB 1 +: S = ("B" > = "A") : GOSUB 1 +: S = ("B" > = "B") : GOSUB 1 +16051 T$ = "=>" +: S = (1 => 1) : GOSUB 1 +: S = (2 => 1) : GOSUB 1 +: S = (1 = > 1) : GOSUB 1 +: S = (2 = > 1) : GOSUB 1 +: S = ("B" => "A") : GOSUB 1 +: S = ("B" => "B") : GOSUB 1 +: S = ("B" = > "A") : GOSUB 1 +: S = ("B" = > "B") : GOSUB 1 + +16060 T$ = "<>" +: S = (1 <> 2) : GOSUB 1 +: S = (1 < > 2) : GOSUB 1 +: S = ("A" <> "B") : GOSUB 1 +: S = ("A" < > "B") : GOSUB 1 +16061 T$ = "><" +: S = (1 >< 2) : GOSUB 1 +: S = (1 > < 2) : GOSUB 1 +: S = ("A" >< "B") : GOSUB 1 +: S = ("A" > < "B") : GOSUB 1 + +16070 T$ = "AND" : S = (1 AND 1) : GOSUB 1 +16080 T$ = "OR" : S = (0 OR 1) : GOSUB 1 +16090 T$ = "NOT" : S = (NOT 0) : GOSUB 1 + +16100 T$ = "^" +: S = (0^0 = 1) : GOSUB 1 +: S = (1^1 = 1) : GOSUB 1 +: S = (2^2 = 4) : GOSUB 1 +: S = (3^0 = 1) : GOSUB 1 +: S = (FN E(1.5^-2 - 0.444)) : GOSUB 1 + +16110 T$ = "*" +: S = (1*0 = 0) : GOSUB 1 +: S = (1*1 = 1) : GOSUB 1 +: S = (-1*1 = -1) : GOSUB 1 +: S = (-1*-1 = 1) : GOSUB 1 +: S = (0.5*2 = 1) : GOSUB 1 + +16120 T$ = "/" +: S = (1/1 = 1) : GOSUB 1 +: S = (-1/1 = -1) : GOSUB 1 +: S = (-1/-1 = 1) : GOSUB 1 +: S = (2/0.5 = 4) : GOSUB 1 + +16130 T$ = "+" +: S = (0+0 = 0) : GOSUB 1 +: S = (0+1 = 1) : GOSUB 1 +: S = (-1+1 = 0) : GOSUB 1 +: S = (1.5+.5 = 2) : GOSUB 1 +: S = ("A"+"B" = "AB") : GOSUB 1 +: S = ("A"+"B"+"C" = "ABC") : GOSUB 1 +: S = (""+"" = "") : GOSUB 1 + +16140 T$ = "-" +: S = (0-0 = 0) : GOSUB 1 +: S = (1-0 = 1) : GOSUB 1 +: S = (-1--1 = 0) : GOSUB 1 +: S = (1.5-.5 = 1) : GOSUB 1 + +16150 T$ = "Precedence" +: S = (FN E((2 + 3 - 4 * 5 / 6 ^ 7) - 4.999)) : GOSUB 1 + +17000 PRINT : PRINT "DOS Commands "; + +17010 PRINT CHR$(4)"OPEN TESTDATA" +: PRINT CHR$(4)"CLOSE TESTDATA" +: PRINT CHR$(4)"DELETE TESTDATA" + +17020 T$ = "Sequential Access OPEN/WRITE/READ" +: PRINT CHR$(4)"OPEN TESTDATA" +: PRINT CHR$(4)"WRITE TESTDATA" +: FOR I = 1 TO 10 : PRINT I : NEXT +: PRINT CHR$(4)"CLOSE TESTDATA" +: PRINT CHR$(4)"OPEN TESTDATA" +: PRINT CHR$(4)"READ TESTDATA" +: T = 0 : FOR I = 1 TO 10 : INPUT J : T = T + J : NEXT +: PRINT CHR$(4)"CLOSE TESTDATA" +: S = (T = 55) : GOSUB 1 + +17030 T$ = "Sequential Access APPEND/WRITE/READ" +: PRINT CHR$(4)"APPEND TESTDATA" +: PRINT CHR$(4)"WRITE TESTDATA" +: FOR I = 1 TO 10 : PRINT -I : NEXT +: PRINT CHR$(4)"CLOSE TESTDATA" +: PRINT CHR$(4)"OPEN TESTDATA" +: PRINT CHR$(4)"READ TESTDATA" +: T = 0 : FOR I = 1 TO 20 : INPUT J : T = T + J : NEXT +: PRINT CHR$(4)"CLOSE TESTDATA" +: S = (T = 0) : GOSUB 1 + +17040 T$ = "Sequential Access/ONERR" +: PRINT CHR$(4)"OPEN JABBERWOCKY" +: PRINT CHR$(4)"READ JABBERWOCKY" +: ONERR GOTO 10742 : N = 0 +: FOR N = 0 TO 10 : INPUT A$ : NEXT +10742 POKE 216,0 : PRINT CHR$(4)"CLOSE" : S = (N = 4) : GOSUB 1 + +17050 T$ = "RENAME" +: PRINT CHR$(4)"OPEN TESTDATA" +: PRINT CHR$(4)"WRITE TESTDATA" +: FOR I = 1 TO 10 : PRINT I : NEXT +: PRINT CHR$(4)"CLOSE TESTDATA" +: PRINT CHR$(4)"RENAME TESTDATA, DATA2" +: PRINT CHR$(4)"OPEN DATA2" +: PRINT CHR$(4)"READ DATA2" +: T = 0 : FOR I = 1 TO 10 : INPUT J : T = T + J : NEXT +: PRINT CHR$(4)"CLOSE DATA2" +: S = (T = 55) : GOSUB 1 + +17500 T$ = "Fixed Length OPEN/WRITE/READ" +: F$ = "FIXEDLENTEST" +: PRINT CHR$(4)"OPEN "F$",L16" +: FOR I = 1 TO 20 : PRINT CHR$(4)"WRITE "F$",R";I : PRINT I * I : NEXT +: PRINT CHR$(4)"CLOSE "F$ +: PRINT CHR$(4)"OPEN "F$",L16" +: T = 0 : FOR I = 20 TO 1 STEP -2 : PRINT CHR$(4)"READ "F$",R";I : INPUT J : T = T + J : NEXT +: PRINT CHR$(4)"CLOSE "F$ +: S = (T = 1540) : GOSUB 1 + +18000 PRINT : PRINT "Regression Tests "; + +18010 T$ = "global rhs in OR" +: T = 0 : FOR I = 1 TO 4 +18011 IF I = 1 OR I = 3 GOTO 18014 +18012 IF I = 2 OR I = 4 GOTO 18014 +18013 T = 1 +18014 NEXT +: S = (T=0) : GOSUB 1 + +18020 T$ = "Operator Associativity" +: S = (10 / 2 * 5 = 25): GOSUB 1 +: S = (2 ^ 3 ^ 4 = 4096): GOSUB 1 + +18030 T$ = "VAL() on bad input" +: S = (VAL("") = 0): GOSUB 1 +: S = (VAL("abc") = 0): GOSUB 1 + +18040 T$ = "Array Dimensions" +: DIM A1(10) : X = A1(10) +: S = (1): GOSUB 1 + +18050 T$ = "Non-integer Array Indices" +: DIM A2(10) : A2(1) = 123 +: S = (A2(1.5) = 123) : GOSUB 1 + +18060 T$ = "Array Lower Bounds" +: T = 1 : ONERR GOTO 18061 +: X = A2(-1) : +: T = 2 +18061 S = (T=1) AND (PEEK(222)=53) : GOSUB 1 : POKE 216,0 + +18070 T$ = "Array Upper Bounds" +: T = 1 : ONERR GOTO 18071 +: X = A2(11) : +: T = 2 +18071 S = (T=1) AND (PEEK(222)=107) : GOSUB 1 : POKE 216,0 + + + + +20000 PRINT : PRINT : PRINT "Executed tests: "; TE +20010 PRINT "Successful tests: "; TS +20019 IF F THEN INVERSE +20020 PRINT "Failed tests: "; F; : NORMAL + + diff --git a/samples/sample.zhorelay.txt b/samples/sample.zhorelay.txt new file mode 100644 index 0000000..6dadff0 --- /dev/null +++ b/samples/sample.zhorelay.txt @@ -0,0 +1,107 @@ +0 REM 5090 Added VTAB 2 to correct display +0 REM Added 5005 to correct display +0 REM 7020 Added PRINT to break lines +0 REM 4892 IF expression will never be true (condition checked earlier) + +100 TEXT : HOME : PRINT "Zhodani Relay Station Placement." +110 PRINT " This program examines an existing sector file and determines the need for, and locations of, Zhodani relay stations (which must be placed between Zhodani naval bases more than four hexes distant)." +120 PRINT " This program originally appeared in Challenge Magazine No. 26." : PRINT + +500 DIM PO(32,40),PP(32,40),OD(13,13) +510 DIM F2(169),F3(169),F4(169),F5(169) +520 DIM F1(169) + +531 NA$(1) = "WORLD " +532 NA$(2) = "ZHO WORLD " +533 NA$(3) = "NAVAL BASE" +534 NA$(4) = "DEPOT " +535 NA$(5) = "RELAY " + +2000 INPUT "Filename? > ";FI$ +2010 PRINT CHR$(4);"OPEN ";FI$;",L50" +2020 PRINT CHR$(4);"READ ";FI$;",R0" +2030 INPUT R +2031 DIM HX$(R) +2040 FOR A = 1 TO R +2050 PRINT CHR$(4);"READ ";FI$;",R";A +2060 INPUT A$ + +3000 X = VAL(LEFT$(A$,2)):Y = VAL(MID$(A$,3,2)) +3001 HX$(A) = LEFT$(A$,4) +3005 Z = 1 +3010 IF MID$(A$,33,1) = "Z" THEN Z = 2 +3020 IF MID$(A$,16,1) = "Z" THEN Z = 3 +3040 IF MID$(A$,16,1) = "Y" THEN Z = 4 +3050 IF MID$(A$,16,1) = "X" THEN Z = 5 +3060 PO(X,Y) = Z : PP(X,Y) = A +3070 NEXT A + + +4000 HOME : FOR X = 1 TO 32 +4005 FOR Y = 1 TO 40 : VTAB 1 +4010 IF PO(X,Y) < 1 THEN 6000 +4012 PRINT "World Hex ";RIGHT$("0"+STR$(X),2);RIGHT$("0"+STR$(Y),2);" ";NA$(PO(X,Y)) +4020 REM +4025 F1 = 0 : F2 = 0 : F3 = 0 : F4 = 0 : F5 = 0 +4027 PRINT "Worlds within jump-4: "; +4028 PRINT : PRINT +4029 FOR N = Y-5 TO Y+5 : FOR M = X-5 to X+5 +4040 IF M < 1 OR M > 32 THEN 4900 +4055 IF N < 1 OR N > 40 THEN 4894 +4056 IF X = M AND N = Y THEN FLASH : PRINT PO(X,Y); : NORMAL : GOTO 4894 +4057 IF X = M AND N <> Y THEN Z1 = ABS(Y-N) : GOTO 4080 +4060 IF Y = N AND X <> M THEN Z1 = ABS(X-M) : GOTO 4080 +4063 EV = 0 : OD = 0 : IF (X/2 = INT(X/2)) AND (M/2 = INT (M/2)) THEN EV=1 +4064 IF (X/2 <> INT(X/2)) AND (M/2 <> INT(M/2)) THEN EV = 1 +4065 IF EV <> 1 THEN OD = 1 +4070 X1 = X - M : Y1 = Y - N : Z1 = SQR((X1*X1)+((.857)*Y1*Y1)) +4071 IF OD = 1 THEN Z1 = Z1 + .5 +4080 IF Z1 > 4 THEN 4890 +4089 IF PO(M,N) = 1 THEN F1 = F1 + 1 : F1(F1) = PP(M,N) +4090 IF PO(M,N) = 2 THEN F2 = F2 + 1 : F2(F2) = PP(M,N) +4100 IF PO(M,N) = 3 THEN F3 = F3 + 1 : F3(F3) = PP(M,N) +4110 IF PO(M,N) = 4 THEN F4 = F4 + 1 : F4(F4) = PP(M,N) +4120 IF PO(M,N) = 5 THEN F5 = F5 + 1 : F5(F5) = PP(M,N) +4180 REM + +4890 IF PO(M,N) = 0 THEN PRINT "."; : GOTO 4894 +4891 PRINT PO(M,N); +4892 IF X = M AND N = Y THEN PRINT "*"; +4894 REM + +4900 NEXT M : PRINT +4902 NEXT N : PRINT + +5000 REM + +5005 VTAB 16 : PRINT : PRINT : PRINT : PRINT : PRINT : PRINT : VTAB 16 + +5010 REM +5011 IF F1 > 0 THEN PRINT NA$(1);": ";F1;"; "; : FOR J = 1 TO F1 : PRINT HX$(F1(J));" "; : NEXT : PRINT +5012 IF F2 > 0 THEN PRINT NA$(2);": ";F2;"; "; : FOR J = 1 TO F2 : PRINT HX$(F2(J));" "; : NEXT : PRINT +5013 IF F3 > 0 THEN PRINT NA$(3);": ";F3;"; "; : FOR J = 1 TO F3 : PRINT HX$(F3(J));" "; : NEXT : PRINT +5014 IF F4 > 0 THEN PRINT NA$(4);": ";F4;"; "; : FOR J = 1 TO F4 : PRINT HX$(F4(J));" "; : NEXT : PRINT +5015 IF F5 > 0 THEN PRINT NA$(5);": ";F5;"; "; : FOR J = 1 TO F5 : PRINT HX$(F5(J));" "; : NEXT : PRINT +5016 IF F2 = 0 THEN 6010 +5017 IF (F3+F4+F5)<>0 THEN 6010 +5018 PRINT "Relay station needed." + +5019 R1 = F2(INT(RND(90)*F2+1)) +5020 PRINT CHR$(4);"OPEN ";FI$;",L50" +5030 PRINT CHR$(4);"READ ";FI$;",R";R1 +5040 INPUT A$ +5050 A$ = LEFT$(A$,15) + "X" + MID$(A$+" ",17,31) +5060 PRINT CHR$(4);"WRITE ";FI$;",R";R1 +5070 PRINT A$ +5080 PRINT CHR$(4);"CLOSE ";FI$ +5090 PO(VAL(LEFT$(A$,2)),VAL(MID$(A$,3,2))) = 5 : VTAB 2 : GOTO 4020 + +6000 REM +6010 NEXT Y +6020 NEXT X + +7000 FOR Y = 1 TO 40 : FOR X = 1 TO 32 +7010 IF PO(X,Y) = 0 THEN PRINT "."; : GOTO 7020 +7015 PRINT PO(X,Y); +7020 NEXT X : PRINT : NEXT Y +7030 END diff --git a/samples/simple.pong.txt b/samples/simple.pong.txt new file mode 100644 index 0000000..779bfcf --- /dev/null +++ b/samples/simple.pong.txt @@ -0,0 +1,142 @@ +0 REM +1 REM Newsgroups: comp.sys.apple2 +2 REM From: mad.scientist.jr@gmail.com +3 REM Message-ID: <1193160910.224728.270640@z24g2000prh.googlegroups.com> +4 REM Subject: Re: woz' original "brick out" - source code , paddles +5 REM Date: Tue, 23 Oct 2007 17:35:10 -0000 +6 REM + +10 REM APPLE II SIMPLE PONG V4 +20 REM PASTE INTO Joshua Bell s EMULATOR AT www.calormen.com/Applesoft/ +25 REM ++++++++++++++++++++++++++++++++++++++++ +30 REM TITLE SCREEN + PROMPT FOR CONTROLS +35 REM ++++++++++++++++++++++++++++++++++++++++ +40 TEXT : REM ENTER TEXT MODE +45 HOME : REM CLEAR TEXT SCREEN +49 PRINT "APPLE II SIMPLE PONG V4" +50 PRINT +51 PRINT "version 1 by aiiadict" +52 PRINT "tweaks by Mad Scientist Jr" +54 PRINT +55 PRINT "During game press Q to quit." +56 PRINT +58 INPUT "TYPE K FOR KEYS (A/Z, K/M) OR P FOR PADDLES OR Q TO QUIT? ";C$ +60 IF C$ <> "K" AND C$ <> "P" AND C$ <> "Q" THEN GOTO 58 +62 IF C$ = "Q" THEN GOTO 9000 +65 REM +70 REM ++++++++++++++++++++++++++++++++++++++++ +75 REM DRAW FIELD AND INITIALIZE GAME +80 REM ++++++++++++++++++++++++++++++++++++++++ +85 GR: REM ENTER GRAPHIC MODE +90 COLOR= 7: VLIN 0,39 AT 0: VLIN 0,39 AT 39 +95 HLIN 0,39 AT 0: HLIN 0,39 AT 39 +100 bx = 10:by = 10:ox = 10:oy = 10: REM BALL START POSITION +102 dx = 1: dy = - 1: REM BALL DIRECTION +104 p1 = 10: o1 = 10: REM PLAYER 1 START POSITION +106 p2 = 10: o2 = 10: REM PLAYER 2 START POSITION +120 PL = 8: REM PADDLE LENGTH +130 REM +145 REM ++++++++++++++++++++++++++++++++++++++++ +150 REM BEGIN MAIN GAME LOOP +155 REM ++++++++++++++++++++++++++++++++++++++++ +196 REM ++++++++++++++++++++++++++++++++++++++++ +197 REM DRAW PADDLE1 +198 REM ++++++++++++++++++++++++++++++++++++++++ +200 IF o1 <> p1 THEN COLOR= 0: VLIN o1,o1 + PL AT 3 +210 COLOR= 7: VLIN p1,p1 + PL AT 3 +296 REM ++++++++++++++++++++++++++++++++++++++++ +297 REM DRAW PADDLE2 +298 REM ++++++++++++++++++++++++++++++++++++++++ +300 IF o2 <> p2 THEN COLOR= 0: VLIN o2,o2 + PL AT 36 +310 COLOR= 7: VLIN p2,p2 + PL AT 36 +399 REM ++++++++++++++++++++++++++++++++++++++++ +400 REM DRAW AND MOVE BALL +401 REM ++++++++++++++++++++++++++++++++++++++++ +402 IF ox <> bx OR oy <> by THEN COLOR= 0: PLOT ox,oy: PLOT ox,oy + 1 +410 COLOR= 5: PLOT bx,by: PLOT bx,by + 1 +416 ox = bx:oy = by +830 bx = bx + dx +835 IF SCRN( bx,by) > 0 THEN dx = - dx +840 by = by + dy +845 IF SCRN( bx,by) > 0 THEN dy = - dy +850 IF bx < 1 THEN bx = 1 +860 IF bx > 38 THEN bx = 38 +870 IF by < 1 THEN by = 1 +880 IF by > 38 THEN by = 38 +881 REM +882 REM ---------------------------------------- +883 REM SAVE OLD SCREEN POSITION +884 REM ---------------------------------------- +885 o1 = p1 +886 o2 = p2 +889 REM +900 REM ++++++++++++++++++++++++++++++++++++++++ +901 REM GET PLAYER INPUT +902 REM ++++++++++++++++++++++++++++++++++++++++ +903 IF PEEK ( - 16384) > 127 THEN GET K$: REM SEE IF KEY(S) PRESSED. NEEDS FIX FOR MULTI KEY SIMULTANEOUS INPUT +904 IF C$ <> "K" THEN GOTO 921 +905 REM +906 REM ---------------------------------------- +907 REM KEYBOARD INPUT +908 REM NOTE: NEEDS FIX TO DETECT MULTI KEYPRESSES +909 REM ---------------------------------------- +912 IF K$ = "A" THEN p1 = p1 - 1 +914 IF K$ = "Z" THEN p1 = p1 + 1 +916 IF K$ = "K" THEN p2 = p2 - 1 +918 IF K$ = "M" THEN p2 = p2 + 1 +920 GOTO 955 +921 IF C$ <> "P" THEN GOTO 947 +922 REM +923 REM ---------------------------------------- +925 REM PADDLE INPUT +927 REM ---------------------------------------- +930 REM simple (non-absolute) paddle input: +931 REM if pdl(0) > 200 then p1 = p1 + 1 +932 REM if pdl(0) < 55 then p1 = p1 - 1 +933 REM if pdl(1) > 200 then p2 = p2 + 1 +934 REM if pdl(1) < 55 then p2 = p2 - 1 +943 REM realtime (absolute position) paddle input: +944 GOSUB 3000: REM PLAYER 1 +945 GOSUB 4000: REM PLAYER 2 +947 REM +948 REM ---------------------------------------- +949 REM SEE IF PLAYER PRESSED Q TO QUIT +950 REM ---------------------------------------- +951 IF K$ = "Q" THEN GOTO 9000 +954 REM +955 REM ++++++++++++++++++++++++++++++++++++++++ +956 REM MAKE SURE PADDLES DONT GO OFF SCREEN +958 REM ++++++++++++++++++++++++++++++++++++++++ +960 IF p1 < 2 THEN p1 = 2 +970 IF p1 > 28 THEN p1 = 28 +980 IF p2 < 2 THEN p2 = 2 +990 IF p2 > 28 THEN p2 = 28 +1000 REM +1010 REM ++++++++++++++++++++++++++++++++++++++++ +1020 REM CONTINUE GAME LOOP +1030 REM ++++++++++++++++++++++++++++++++++++++++ +1040 GOTO 150 +3000 REM +3010 REM ++++++++++++++++++++++++++++++++++++++++ +3020 REM GET SCREEN POSITION FROM PADDLE 1 INPUT +3030 REM ++++++++++++++++++++++++++++++++++++++++ +3040 p1 = 26 * pdl(0) +3050 p1 = p1 / 255 +3060 p1 = p1 + 2 +3070 RETURN +4000 REM +4010 REM ++++++++++++++++++++++++++++++++++++++++ +4020 REM GET SCREEN POSITION FROM PADDLE 2 INPUT +4030 REM ++++++++++++++++++++++++++++++++++++++++ +4040 p2 = 26 * pdl(1) +4050 p2 = p2 / 255 +4060 p2 = p2 + 2 +4070 RETURN +9000 REM +9010 REM ++++++++++++++++++++++++++++++++++++++++ +9020 REM QUIT GAME +9030 REM ++++++++++++++++++++++++++++++++++++++++ +9040 TEXT : REM HOME +9045 PRINT +9050 PRINT "FINISHED APPLE II SIMPLE PONG V4." +9060 END \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..2f880d8 --- /dev/null +++ b/styles.css @@ -0,0 +1,968 @@ + +body { background-color: #EEEACD; } +h1, h2, h3, p { margin-bottom: 6pt; margin-top: 6pt; } +td { vertical-align: top; } + + +/* Apple II Screen */ +.frame {width: 560px; height: 384px; border-style: ridge; border-width: 10px; border-color: gray; padding: 10px; background-color: #202020; } +.wrapper { width: 560px; height: 384px; overflow: hidden; padding: 0; margin: 0; position: relative; } +.lores {position: absolute; z-index: 2; left: 0; top: 0; width: 560px; height: 384px; overflow: hidden; visibility: hidden; } +.hires {position: absolute; z-index: 2; left: 0; top: 0; width: 560px; height: 384px; overflow: hidden; visibility: hidden; background-color: #000000; } +.tty {position: absolute; z-index: 3; left: 0; top: 0; width: 560px; height: 384px; overflow: hidden; } + +/* Character cells */ +.normal { background-color: #000000; color: #80ff80; } +.inverse { background-color: #80ff80; color: #000000; } +.row { background-color: #000000; } /* Background leaks through on safari even with margin/padding/border of 0 */ + +.a2c { height: 16px; line-height: 0; border: 0; padding: 0; margin: 0; background-repeat:no-repeat; } +.a2c-cursor { position: relative; display: inline-block; } +.tty_tr { height: 16px; } +.tty_table { table-layout: fixed; border-collapse: collapse; } + +/* + function pos(code, sw) { + var x = Math.floor(code / 16); + var y = code % 16; + x = -( sw > 40 ? 1 : 2 )* (3 + 13 * x); + y = -2 * (4 + 13 * y); + return String(x) + 'px ' + String(y) + 'px'; + } + function gen(cc, sc, sw, styles) { + console.log('.tty_'+sw+'col'+styles+' .a2c'+cc+' { background-position: '+ pos(sc,sw)+' }'); + } + for( sw = 40; sw <= 80; sw += 40) { + // 0x00-0x1F = INVERSE @ABC…XYZ[\]^_ + // 0x20-0x3F = INVERSE !"#$…<=>? + + for (i = 0x00; i < 0x20; i++) { gen(i+0x00, i+0xC0, sw, ''); } + for (i = 0x00; i < 0x20; i++) { gen(i+0x20, i+0xA0, sw, ''); } + + // 80-column firmware inactive + // 0x40-0x5F = FLASH @ABC…XYZ[\]^_ + // 0x60-0x7F = FLASH !"#$…<=>? + + for (i = 0x00; i < 0x20; i++) { gen(i+0x40, i+0x40, sw, ''); } + for (i = 0x00; i < 0x20; i++) { gen(i+0x40, i+0xC0, sw, '.flash'); } + for (i = 0x00; i < 0x20; i++) { gen(i+0x60, i+0x20, sw, ''); } + for (i = 0x00; i < 0x20; i++) { gen(i+0x60, i+0xA0, sw, '.flash'); } + + // 80-column firmware active + // 0x40-0x5F = MOUSETEXT + // 0x60-0x7F = INVERSE `abc…{|}~ + + for (i = 0x00; i < 0x20; i++) { gen(i+0x40, i+0x80, sw, '.active'); } + for (i = 0x00; i < 0x20; i++) { gen(i+0x60, i+0xE0, sw, '.active'); } + + // 0x80-0x9F = NORMAL @ABC…XYZ[\]^_ + // 0xA0-0xBF = NORMAL !"#$…<=>? + // 0xC0-0xDF = NORMAL @ABC…XYZ[\]^_ + // 0xE0-0xFF = NORMAL `abc…{|}~ + + for (i = 0x00; i < 0x20; i++) { gen(i+0x80, i+0x40, sw, ''); } + for (i = 0x00; i < 0x20; i++) { gen(i+0xA0, i+0x20, sw, ''); } + for (i = 0x00; i < 0x20; i++) { gen(i+0xC0, i+0x40, sw, ''); } + for (i = 0x00; i < 0x20; i++) { gen(i+0xE0, i+0x60, sw, ''); } + + // Extension symbols + for (i = 0x00; i < 0x20; i++) { gen(i+0x100, i+0x100, sw, ''); } + } +*/ + +/* 40 Column Text */ +.tty_40col .a2c { background-image: url(font-40col.png); width: 14px; } + +/* 80 Column Text */ +.tty_80col .a2c { background-image: url(font-80col.png); width: 7px; } + +.tty_40col .a2c0 { background-position: -318px -8px } +.tty_40col .a2c1 { background-position: -318px -34px } +.tty_40col .a2c2 { background-position: -318px -60px } +.tty_40col .a2c3 { background-position: -318px -86px } +.tty_40col .a2c4 { background-position: -318px -112px } +.tty_40col .a2c5 { background-position: -318px -138px } +.tty_40col .a2c6 { background-position: -318px -164px } +.tty_40col .a2c7 { background-position: -318px -190px } +.tty_40col .a2c8 { background-position: -318px -216px } +.tty_40col .a2c9 { background-position: -318px -242px } +.tty_40col .a2c10 { background-position: -318px -268px } +.tty_40col .a2c11 { background-position: -318px -294px } +.tty_40col .a2c12 { background-position: -318px -320px } +.tty_40col .a2c13 { background-position: -318px -346px } +.tty_40col .a2c14 { background-position: -318px -372px } +.tty_40col .a2c15 { background-position: -318px -398px } +.tty_40col .a2c16 { background-position: -344px -8px } +.tty_40col .a2c17 { background-position: -344px -34px } +.tty_40col .a2c18 { background-position: -344px -60px } +.tty_40col .a2c19 { background-position: -344px -86px } +.tty_40col .a2c20 { background-position: -344px -112px } +.tty_40col .a2c21 { background-position: -344px -138px } +.tty_40col .a2c22 { background-position: -344px -164px } +.tty_40col .a2c23 { background-position: -344px -190px } +.tty_40col .a2c24 { background-position: -344px -216px } +.tty_40col .a2c25 { background-position: -344px -242px } +.tty_40col .a2c26 { background-position: -344px -268px } +.tty_40col .a2c27 { background-position: -344px -294px } +.tty_40col .a2c28 { background-position: -344px -320px } +.tty_40col .a2c29 { background-position: -344px -346px } +.tty_40col .a2c30 { background-position: -344px -372px } +.tty_40col .a2c31 { background-position: -344px -398px } +.tty_40col .a2c32 { background-position: -266px -8px } +.tty_40col .a2c33 { background-position: -266px -34px } +.tty_40col .a2c34 { background-position: -266px -60px } +.tty_40col .a2c35 { background-position: -266px -86px } +.tty_40col .a2c36 { background-position: -266px -112px } +.tty_40col .a2c37 { background-position: -266px -138px } +.tty_40col .a2c38 { background-position: -266px -164px } +.tty_40col .a2c39 { background-position: -266px -190px } +.tty_40col .a2c40 { background-position: -266px -216px } +.tty_40col .a2c41 { background-position: -266px -242px } +.tty_40col .a2c42 { background-position: -266px -268px } +.tty_40col .a2c43 { background-position: -266px -294px } +.tty_40col .a2c44 { background-position: -266px -320px } +.tty_40col .a2c45 { background-position: -266px -346px } +.tty_40col .a2c46 { background-position: -266px -372px } +.tty_40col .a2c47 { background-position: -266px -398px } +.tty_40col .a2c48 { background-position: -292px -8px } +.tty_40col .a2c49 { background-position: -292px -34px } +.tty_40col .a2c50 { background-position: -292px -60px } +.tty_40col .a2c51 { background-position: -292px -86px } +.tty_40col .a2c52 { background-position: -292px -112px } +.tty_40col .a2c53 { background-position: -292px -138px } +.tty_40col .a2c54 { background-position: -292px -164px } +.tty_40col .a2c55 { background-position: -292px -190px } +.tty_40col .a2c56 { background-position: -292px -216px } +.tty_40col .a2c57 { background-position: -292px -242px } +.tty_40col .a2c58 { background-position: -292px -268px } +.tty_40col .a2c59 { background-position: -292px -294px } +.tty_40col .a2c60 { background-position: -292px -320px } +.tty_40col .a2c61 { background-position: -292px -346px } +.tty_40col .a2c62 { background-position: -292px -372px } +.tty_40col .a2c63 { background-position: -292px -398px } +.tty_40col .a2c64 { background-position: -110px -8px } +.tty_40col .a2c65 { background-position: -110px -34px } +.tty_40col .a2c66 { background-position: -110px -60px } +.tty_40col .a2c67 { background-position: -110px -86px } +.tty_40col .a2c68 { background-position: -110px -112px } +.tty_40col .a2c69 { background-position: -110px -138px } +.tty_40col .a2c70 { background-position: -110px -164px } +.tty_40col .a2c71 { background-position: -110px -190px } +.tty_40col .a2c72 { background-position: -110px -216px } +.tty_40col .a2c73 { background-position: -110px -242px } +.tty_40col .a2c74 { background-position: -110px -268px } +.tty_40col .a2c75 { background-position: -110px -294px } +.tty_40col .a2c76 { background-position: -110px -320px } +.tty_40col .a2c77 { background-position: -110px -346px } +.tty_40col .a2c78 { background-position: -110px -372px } +.tty_40col .a2c79 { background-position: -110px -398px } +.tty_40col .a2c80 { background-position: -136px -8px } +.tty_40col .a2c81 { background-position: -136px -34px } +.tty_40col .a2c82 { background-position: -136px -60px } +.tty_40col .a2c83 { background-position: -136px -86px } +.tty_40col .a2c84 { background-position: -136px -112px } +.tty_40col .a2c85 { background-position: -136px -138px } +.tty_40col .a2c86 { background-position: -136px -164px } +.tty_40col .a2c87 { background-position: -136px -190px } +.tty_40col .a2c88 { background-position: -136px -216px } +.tty_40col .a2c89 { background-position: -136px -242px } +.tty_40col .a2c90 { background-position: -136px -268px } +.tty_40col .a2c91 { background-position: -136px -294px } +.tty_40col .a2c92 { background-position: -136px -320px } +.tty_40col .a2c93 { background-position: -136px -346px } +.tty_40col .a2c94 { background-position: -136px -372px } +.tty_40col .a2c95 { background-position: -136px -398px } +.tty_40col.flash .a2c64 { background-position: -318px -8px } +.tty_40col.flash .a2c65 { background-position: -318px -34px } +.tty_40col.flash .a2c66 { background-position: -318px -60px } +.tty_40col.flash .a2c67 { background-position: -318px -86px } +.tty_40col.flash .a2c68 { background-position: -318px -112px } +.tty_40col.flash .a2c69 { background-position: -318px -138px } +.tty_40col.flash .a2c70 { background-position: -318px -164px } +.tty_40col.flash .a2c71 { background-position: -318px -190px } +.tty_40col.flash .a2c72 { background-position: -318px -216px } +.tty_40col.flash .a2c73 { background-position: -318px -242px } +.tty_40col.flash .a2c74 { background-position: -318px -268px } +.tty_40col.flash .a2c75 { background-position: -318px -294px } +.tty_40col.flash .a2c76 { background-position: -318px -320px } +.tty_40col.flash .a2c77 { background-position: -318px -346px } +.tty_40col.flash .a2c78 { background-position: -318px -372px } +.tty_40col.flash .a2c79 { background-position: -318px -398px } +.tty_40col.flash .a2c80 { background-position: -344px -8px } +.tty_40col.flash .a2c81 { background-position: -344px -34px } +.tty_40col.flash .a2c82 { background-position: -344px -60px } +.tty_40col.flash .a2c83 { background-position: -344px -86px } +.tty_40col.flash .a2c84 { background-position: -344px -112px } +.tty_40col.flash .a2c85 { background-position: -344px -138px } +.tty_40col.flash .a2c86 { background-position: -344px -164px } +.tty_40col.flash .a2c87 { background-position: -344px -190px } +.tty_40col.flash .a2c88 { background-position: -344px -216px } +.tty_40col.flash .a2c89 { background-position: -344px -242px } +.tty_40col.flash .a2c90 { background-position: -344px -268px } +.tty_40col.flash .a2c91 { background-position: -344px -294px } +.tty_40col.flash .a2c92 { background-position: -344px -320px } +.tty_40col.flash .a2c93 { background-position: -344px -346px } +.tty_40col.flash .a2c94 { background-position: -344px -372px } +.tty_40col.flash .a2c95 { background-position: -344px -398px } +.tty_40col .a2c96 { background-position: -58px -8px } +.tty_40col .a2c97 { background-position: -58px -34px } +.tty_40col .a2c98 { background-position: -58px -60px } +.tty_40col .a2c99 { background-position: -58px -86px } +.tty_40col .a2c100 { background-position: -58px -112px } +.tty_40col .a2c101 { background-position: -58px -138px } +.tty_40col .a2c102 { background-position: -58px -164px } +.tty_40col .a2c103 { background-position: -58px -190px } +.tty_40col .a2c104 { background-position: -58px -216px } +.tty_40col .a2c105 { background-position: -58px -242px } +.tty_40col .a2c106 { background-position: -58px -268px } +.tty_40col .a2c107 { background-position: -58px -294px } +.tty_40col .a2c108 { background-position: -58px -320px } +.tty_40col .a2c109 { background-position: -58px -346px } +.tty_40col .a2c110 { background-position: -58px -372px } +.tty_40col .a2c111 { background-position: -58px -398px } +.tty_40col .a2c112 { background-position: -84px -8px } +.tty_40col .a2c113 { background-position: -84px -34px } +.tty_40col .a2c114 { background-position: -84px -60px } +.tty_40col .a2c115 { background-position: -84px -86px } +.tty_40col .a2c116 { background-position: -84px -112px } +.tty_40col .a2c117 { background-position: -84px -138px } +.tty_40col .a2c118 { background-position: -84px -164px } +.tty_40col .a2c119 { background-position: -84px -190px } +.tty_40col .a2c120 { background-position: -84px -216px } +.tty_40col .a2c121 { background-position: -84px -242px } +.tty_40col .a2c122 { background-position: -84px -268px } +.tty_40col .a2c123 { background-position: -84px -294px } +.tty_40col .a2c124 { background-position: -84px -320px } +.tty_40col .a2c125 { background-position: -84px -346px } +.tty_40col .a2c126 { background-position: -84px -372px } +.tty_40col .a2c127 { background-position: -84px -398px } +.tty_40col.flash .a2c96 { background-position: -266px -8px } +.tty_40col.flash .a2c97 { background-position: -266px -34px } +.tty_40col.flash .a2c98 { background-position: -266px -60px } +.tty_40col.flash .a2c99 { background-position: -266px -86px } +.tty_40col.flash .a2c100 { background-position: -266px -112px } +.tty_40col.flash .a2c101 { background-position: -266px -138px } +.tty_40col.flash .a2c102 { background-position: -266px -164px } +.tty_40col.flash .a2c103 { background-position: -266px -190px } +.tty_40col.flash .a2c104 { background-position: -266px -216px } +.tty_40col.flash .a2c105 { background-position: -266px -242px } +.tty_40col.flash .a2c106 { background-position: -266px -268px } +.tty_40col.flash .a2c107 { background-position: -266px -294px } +.tty_40col.flash .a2c108 { background-position: -266px -320px } +.tty_40col.flash .a2c109 { background-position: -266px -346px } +.tty_40col.flash .a2c110 { background-position: -266px -372px } +.tty_40col.flash .a2c111 { background-position: -266px -398px } +.tty_40col.flash .a2c112 { background-position: -292px -8px } +.tty_40col.flash .a2c113 { background-position: -292px -34px } +.tty_40col.flash .a2c114 { background-position: -292px -60px } +.tty_40col.flash .a2c115 { background-position: -292px -86px } +.tty_40col.flash .a2c116 { background-position: -292px -112px } +.tty_40col.flash .a2c117 { background-position: -292px -138px } +.tty_40col.flash .a2c118 { background-position: -292px -164px } +.tty_40col.flash .a2c119 { background-position: -292px -190px } +.tty_40col.flash .a2c120 { background-position: -292px -216px } +.tty_40col.flash .a2c121 { background-position: -292px -242px } +.tty_40col.flash .a2c122 { background-position: -292px -268px } +.tty_40col.flash .a2c123 { background-position: -292px -294px } +.tty_40col.flash .a2c124 { background-position: -292px -320px } +.tty_40col.flash .a2c125 { background-position: -292px -346px } +.tty_40col.flash .a2c126 { background-position: -292px -372px } +.tty_40col.flash .a2c127 { background-position: -292px -398px } +.tty_40col.active .a2c64 { background-position: -214px -8px } +.tty_40col.active .a2c65 { background-position: -214px -34px } +.tty_40col.active .a2c66 { background-position: -214px -60px } +.tty_40col.active .a2c67 { background-position: -214px -86px } +.tty_40col.active .a2c68 { background-position: -214px -112px } +.tty_40col.active .a2c69 { background-position: -214px -138px } +.tty_40col.active .a2c70 { background-position: -214px -164px } +.tty_40col.active .a2c71 { background-position: -214px -190px } +.tty_40col.active .a2c72 { background-position: -214px -216px } +.tty_40col.active .a2c73 { background-position: -214px -242px } +.tty_40col.active .a2c74 { background-position: -214px -268px } +.tty_40col.active .a2c75 { background-position: -214px -294px } +.tty_40col.active .a2c76 { background-position: -214px -320px } +.tty_40col.active .a2c77 { background-position: -214px -346px } +.tty_40col.active .a2c78 { background-position: -214px -372px } +.tty_40col.active .a2c79 { background-position: -214px -398px } +.tty_40col.active .a2c80 { background-position: -240px -8px } +.tty_40col.active .a2c81 { background-position: -240px -34px } +.tty_40col.active .a2c82 { background-position: -240px -60px } +.tty_40col.active .a2c83 { background-position: -240px -86px } +.tty_40col.active .a2c84 { background-position: -240px -112px } +.tty_40col.active .a2c85 { background-position: -240px -138px } +.tty_40col.active .a2c86 { background-position: -240px -164px } +.tty_40col.active .a2c87 { background-position: -240px -190px } +.tty_40col.active .a2c88 { background-position: -240px -216px } +.tty_40col.active .a2c89 { background-position: -240px -242px } +.tty_40col.active .a2c90 { background-position: -240px -268px } +.tty_40col.active .a2c91 { background-position: -240px -294px } +.tty_40col.active .a2c92 { background-position: -240px -320px } +.tty_40col.active .a2c93 { background-position: -240px -346px } +.tty_40col.active .a2c94 { background-position: -240px -372px } +.tty_40col.active .a2c95 { background-position: -240px -398px } +.tty_40col.active .a2c96 { background-position: -370px -8px } +.tty_40col.active .a2c97 { background-position: -370px -34px } +.tty_40col.active .a2c98 { background-position: -370px -60px } +.tty_40col.active .a2c99 { background-position: -370px -86px } +.tty_40col.active .a2c100 { background-position: -370px -112px } +.tty_40col.active .a2c101 { background-position: -370px -138px } +.tty_40col.active .a2c102 { background-position: -370px -164px } +.tty_40col.active .a2c103 { background-position: -370px -190px } +.tty_40col.active .a2c104 { background-position: -370px -216px } +.tty_40col.active .a2c105 { background-position: -370px -242px } +.tty_40col.active .a2c106 { background-position: -370px -268px } +.tty_40col.active .a2c107 { background-position: -370px -294px } +.tty_40col.active .a2c108 { background-position: -370px -320px } +.tty_40col.active .a2c109 { background-position: -370px -346px } +.tty_40col.active .a2c110 { background-position: -370px -372px } +.tty_40col.active .a2c111 { background-position: -370px -398px } +.tty_40col.active .a2c112 { background-position: -396px -8px } +.tty_40col.active .a2c113 { background-position: -396px -34px } +.tty_40col.active .a2c114 { background-position: -396px -60px } +.tty_40col.active .a2c115 { background-position: -396px -86px } +.tty_40col.active .a2c116 { background-position: -396px -112px } +.tty_40col.active .a2c117 { background-position: -396px -138px } +.tty_40col.active .a2c118 { background-position: -396px -164px } +.tty_40col.active .a2c119 { background-position: -396px -190px } +.tty_40col.active .a2c120 { background-position: -396px -216px } +.tty_40col.active .a2c121 { background-position: -396px -242px } +.tty_40col.active .a2c122 { background-position: -396px -268px } +.tty_40col.active .a2c123 { background-position: -396px -294px } +.tty_40col.active .a2c124 { background-position: -396px -320px } +.tty_40col.active .a2c125 { background-position: -396px -346px } +.tty_40col.active .a2c126 { background-position: -396px -372px } +.tty_40col.active .a2c127 { background-position: -396px -398px } +.tty_40col .a2c128 { background-position: -110px -8px } +.tty_40col .a2c129 { background-position: -110px -34px } +.tty_40col .a2c130 { background-position: -110px -60px } +.tty_40col .a2c131 { background-position: -110px -86px } +.tty_40col .a2c132 { background-position: -110px -112px } +.tty_40col .a2c133 { background-position: -110px -138px } +.tty_40col .a2c134 { background-position: -110px -164px } +.tty_40col .a2c135 { background-position: -110px -190px } +.tty_40col .a2c136 { background-position: -110px -216px } +.tty_40col .a2c137 { background-position: -110px -242px } +.tty_40col .a2c138 { background-position: -110px -268px } +.tty_40col .a2c139 { background-position: -110px -294px } +.tty_40col .a2c140 { background-position: -110px -320px } +.tty_40col .a2c141 { background-position: -110px -346px } +.tty_40col .a2c142 { background-position: -110px -372px } +.tty_40col .a2c143 { background-position: -110px -398px } +.tty_40col .a2c144 { background-position: -136px -8px } +.tty_40col .a2c145 { background-position: -136px -34px } +.tty_40col .a2c146 { background-position: -136px -60px } +.tty_40col .a2c147 { background-position: -136px -86px } +.tty_40col .a2c148 { background-position: -136px -112px } +.tty_40col .a2c149 { background-position: -136px -138px } +.tty_40col .a2c150 { background-position: -136px -164px } +.tty_40col .a2c151 { background-position: -136px -190px } +.tty_40col .a2c152 { background-position: -136px -216px } +.tty_40col .a2c153 { background-position: -136px -242px } +.tty_40col .a2c154 { background-position: -136px -268px } +.tty_40col .a2c155 { background-position: -136px -294px } +.tty_40col .a2c156 { background-position: -136px -320px } +.tty_40col .a2c157 { background-position: -136px -346px } +.tty_40col .a2c158 { background-position: -136px -372px } +.tty_40col .a2c159 { background-position: -136px -398px } +.tty_40col .a2c160 { background-position: -58px -8px } +.tty_40col .a2c161 { background-position: -58px -34px } +.tty_40col .a2c162 { background-position: -58px -60px } +.tty_40col .a2c163 { background-position: -58px -86px } +.tty_40col .a2c164 { background-position: -58px -112px } +.tty_40col .a2c165 { background-position: -58px -138px } +.tty_40col .a2c166 { background-position: -58px -164px } +.tty_40col .a2c167 { background-position: -58px -190px } +.tty_40col .a2c168 { background-position: -58px -216px } +.tty_40col .a2c169 { background-position: -58px -242px } +.tty_40col .a2c170 { background-position: -58px -268px } +.tty_40col .a2c171 { background-position: -58px -294px } +.tty_40col .a2c172 { background-position: -58px -320px } +.tty_40col .a2c173 { background-position: -58px -346px } +.tty_40col .a2c174 { background-position: -58px -372px } +.tty_40col .a2c175 { background-position: -58px -398px } +.tty_40col .a2c176 { background-position: -84px -8px } +.tty_40col .a2c177 { background-position: -84px -34px } +.tty_40col .a2c178 { background-position: -84px -60px } +.tty_40col .a2c179 { background-position: -84px -86px } +.tty_40col .a2c180 { background-position: -84px -112px } +.tty_40col .a2c181 { background-position: -84px -138px } +.tty_40col .a2c182 { background-position: -84px -164px } +.tty_40col .a2c183 { background-position: -84px -190px } +.tty_40col .a2c184 { background-position: -84px -216px } +.tty_40col .a2c185 { background-position: -84px -242px } +.tty_40col .a2c186 { background-position: -84px -268px } +.tty_40col .a2c187 { background-position: -84px -294px } +.tty_40col .a2c188 { background-position: -84px -320px } +.tty_40col .a2c189 { background-position: -84px -346px } +.tty_40col .a2c190 { background-position: -84px -372px } +.tty_40col .a2c191 { background-position: -84px -398px } +.tty_40col .a2c192 { background-position: -110px -8px } +.tty_40col .a2c193 { background-position: -110px -34px } +.tty_40col .a2c194 { background-position: -110px -60px } +.tty_40col .a2c195 { background-position: -110px -86px } +.tty_40col .a2c196 { background-position: -110px -112px } +.tty_40col .a2c197 { background-position: -110px -138px } +.tty_40col .a2c198 { background-position: -110px -164px } +.tty_40col .a2c199 { background-position: -110px -190px } +.tty_40col .a2c200 { background-position: -110px -216px } +.tty_40col .a2c201 { background-position: -110px -242px } +.tty_40col .a2c202 { background-position: -110px -268px } +.tty_40col .a2c203 { background-position: -110px -294px } +.tty_40col .a2c204 { background-position: -110px -320px } +.tty_40col .a2c205 { background-position: -110px -346px } +.tty_40col .a2c206 { background-position: -110px -372px } +.tty_40col .a2c207 { background-position: -110px -398px } +.tty_40col .a2c208 { background-position: -136px -8px } +.tty_40col .a2c209 { background-position: -136px -34px } +.tty_40col .a2c210 { background-position: -136px -60px } +.tty_40col .a2c211 { background-position: -136px -86px } +.tty_40col .a2c212 { background-position: -136px -112px } +.tty_40col .a2c213 { background-position: -136px -138px } +.tty_40col .a2c214 { background-position: -136px -164px } +.tty_40col .a2c215 { background-position: -136px -190px } +.tty_40col .a2c216 { background-position: -136px -216px } +.tty_40col .a2c217 { background-position: -136px -242px } +.tty_40col .a2c218 { background-position: -136px -268px } +.tty_40col .a2c219 { background-position: -136px -294px } +.tty_40col .a2c220 { background-position: -136px -320px } +.tty_40col .a2c221 { background-position: -136px -346px } +.tty_40col .a2c222 { background-position: -136px -372px } +.tty_40col .a2c223 { background-position: -136px -398px } +.tty_40col .a2c224 { background-position: -162px -8px } +.tty_40col .a2c225 { background-position: -162px -34px } +.tty_40col .a2c226 { background-position: -162px -60px } +.tty_40col .a2c227 { background-position: -162px -86px } +.tty_40col .a2c228 { background-position: -162px -112px } +.tty_40col .a2c229 { background-position: -162px -138px } +.tty_40col .a2c230 { background-position: -162px -164px } +.tty_40col .a2c231 { background-position: -162px -190px } +.tty_40col .a2c232 { background-position: -162px -216px } +.tty_40col .a2c233 { background-position: -162px -242px } +.tty_40col .a2c234 { background-position: -162px -268px } +.tty_40col .a2c235 { background-position: -162px -294px } +.tty_40col .a2c236 { background-position: -162px -320px } +.tty_40col .a2c237 { background-position: -162px -346px } +.tty_40col .a2c238 { background-position: -162px -372px } +.tty_40col .a2c239 { background-position: -162px -398px } +.tty_40col .a2c240 { background-position: -188px -8px } +.tty_40col .a2c241 { background-position: -188px -34px } +.tty_40col .a2c242 { background-position: -188px -60px } +.tty_40col .a2c243 { background-position: -188px -86px } +.tty_40col .a2c244 { background-position: -188px -112px } +.tty_40col .a2c245 { background-position: -188px -138px } +.tty_40col .a2c246 { background-position: -188px -164px } +.tty_40col .a2c247 { background-position: -188px -190px } +.tty_40col .a2c248 { background-position: -188px -216px } +.tty_40col .a2c249 { background-position: -188px -242px } +.tty_40col .a2c250 { background-position: -188px -268px } +.tty_40col .a2c251 { background-position: -188px -294px } +.tty_40col .a2c252 { background-position: -188px -320px } +.tty_40col .a2c253 { background-position: -188px -346px } +.tty_40col .a2c254 { background-position: -188px -372px } +.tty_40col .a2c255 { background-position: -188px -398px } + +.tty_40col .a2c256 { background-position: -422px -8px } +.tty_40col .a2c257 { background-position: -422px -34px } +.tty_40col .a2c258 { background-position: -422px -60px } +.tty_40col .a2c259 { background-position: -422px -86px } +.tty_40col .a2c260 { background-position: -422px -112px } +.tty_40col .a2c261 { background-position: -422px -138px } +.tty_40col .a2c262 { background-position: -422px -164px } +.tty_40col .a2c263 { background-position: -422px -190px } +.tty_40col .a2c264 { background-position: -422px -216px } +.tty_40col .a2c265 { background-position: -422px -242px } +.tty_40col .a2c266 { background-position: -422px -268px } +.tty_40col .a2c267 { background-position: -422px -294px } +.tty_40col .a2c268 { background-position: -422px -320px } +.tty_40col .a2c269 { background-position: -422px -346px } +.tty_40col .a2c270 { background-position: -422px -372px } +.tty_40col .a2c271 { background-position: -422px -398px } +.tty_40col .a2c272 { background-position: -448px -8px } +.tty_40col .a2c273 { background-position: -448px -34px } +.tty_40col .a2c274 { background-position: -448px -60px } +.tty_40col .a2c275 { background-position: -448px -86px } +.tty_40col .a2c276 { background-position: -448px -112px } +.tty_40col .a2c277 { background-position: -448px -138px } +.tty_40col .a2c278 { background-position: -448px -164px } +.tty_40col .a2c279 { background-position: -448px -190px } +.tty_40col .a2c280 { background-position: -448px -216px } +.tty_40col .a2c281 { background-position: -448px -242px } +.tty_40col .a2c282 { background-position: -448px -268px } +.tty_40col .a2c283 { background-position: -448px -294px } +.tty_40col .a2c284 { background-position: -448px -320px } +.tty_40col .a2c285 { background-position: -448px -346px } +.tty_40col .a2c286 { background-position: -448px -372px } +.tty_40col .a2c287 { background-position: -448px -398px } + +.tty_80col .a2c0 { background-position: -159px -8px } +.tty_80col .a2c1 { background-position: -159px -34px } +.tty_80col .a2c2 { background-position: -159px -60px } +.tty_80col .a2c3 { background-position: -159px -86px } +.tty_80col .a2c4 { background-position: -159px -112px } +.tty_80col .a2c5 { background-position: -159px -138px } +.tty_80col .a2c6 { background-position: -159px -164px } +.tty_80col .a2c7 { background-position: -159px -190px } +.tty_80col .a2c8 { background-position: -159px -216px } +.tty_80col .a2c9 { background-position: -159px -242px } +.tty_80col .a2c10 { background-position: -159px -268px } +.tty_80col .a2c11 { background-position: -159px -294px } +.tty_80col .a2c12 { background-position: -159px -320px } +.tty_80col .a2c13 { background-position: -159px -346px } +.tty_80col .a2c14 { background-position: -159px -372px } +.tty_80col .a2c15 { background-position: -159px -398px } +.tty_80col .a2c16 { background-position: -172px -8px } +.tty_80col .a2c17 { background-position: -172px -34px } +.tty_80col .a2c18 { background-position: -172px -60px } +.tty_80col .a2c19 { background-position: -172px -86px } +.tty_80col .a2c20 { background-position: -172px -112px } +.tty_80col .a2c21 { background-position: -172px -138px } +.tty_80col .a2c22 { background-position: -172px -164px } +.tty_80col .a2c23 { background-position: -172px -190px } +.tty_80col .a2c24 { background-position: -172px -216px } +.tty_80col .a2c25 { background-position: -172px -242px } +.tty_80col .a2c26 { background-position: -172px -268px } +.tty_80col .a2c27 { background-position: -172px -294px } +.tty_80col .a2c28 { background-position: -172px -320px } +.tty_80col .a2c29 { background-position: -172px -346px } +.tty_80col .a2c30 { background-position: -172px -372px } +.tty_80col .a2c31 { background-position: -172px -398px } +.tty_80col .a2c32 { background-position: -133px -8px } +.tty_80col .a2c33 { background-position: -133px -34px } +.tty_80col .a2c34 { background-position: -133px -60px } +.tty_80col .a2c35 { background-position: -133px -86px } +.tty_80col .a2c36 { background-position: -133px -112px } +.tty_80col .a2c37 { background-position: -133px -138px } +.tty_80col .a2c38 { background-position: -133px -164px } +.tty_80col .a2c39 { background-position: -133px -190px } +.tty_80col .a2c40 { background-position: -133px -216px } +.tty_80col .a2c41 { background-position: -133px -242px } +.tty_80col .a2c42 { background-position: -133px -268px } +.tty_80col .a2c43 { background-position: -133px -294px } +.tty_80col .a2c44 { background-position: -133px -320px } +.tty_80col .a2c45 { background-position: -133px -346px } +.tty_80col .a2c46 { background-position: -133px -372px } +.tty_80col .a2c47 { background-position: -133px -398px } +.tty_80col .a2c48 { background-position: -146px -8px } +.tty_80col .a2c49 { background-position: -146px -34px } +.tty_80col .a2c50 { background-position: -146px -60px } +.tty_80col .a2c51 { background-position: -146px -86px } +.tty_80col .a2c52 { background-position: -146px -112px } +.tty_80col .a2c53 { background-position: -146px -138px } +.tty_80col .a2c54 { background-position: -146px -164px } +.tty_80col .a2c55 { background-position: -146px -190px } +.tty_80col .a2c56 { background-position: -146px -216px } +.tty_80col .a2c57 { background-position: -146px -242px } +.tty_80col .a2c58 { background-position: -146px -268px } +.tty_80col .a2c59 { background-position: -146px -294px } +.tty_80col .a2c60 { background-position: -146px -320px } +.tty_80col .a2c61 { background-position: -146px -346px } +.tty_80col .a2c62 { background-position: -146px -372px } +.tty_80col .a2c63 { background-position: -146px -398px } +.tty_80col .a2c64 { background-position: -55px -8px } +.tty_80col .a2c65 { background-position: -55px -34px } +.tty_80col .a2c66 { background-position: -55px -60px } +.tty_80col .a2c67 { background-position: -55px -86px } +.tty_80col .a2c68 { background-position: -55px -112px } +.tty_80col .a2c69 { background-position: -55px -138px } +.tty_80col .a2c70 { background-position: -55px -164px } +.tty_80col .a2c71 { background-position: -55px -190px } +.tty_80col .a2c72 { background-position: -55px -216px } +.tty_80col .a2c73 { background-position: -55px -242px } +.tty_80col .a2c74 { background-position: -55px -268px } +.tty_80col .a2c75 { background-position: -55px -294px } +.tty_80col .a2c76 { background-position: -55px -320px } +.tty_80col .a2c77 { background-position: -55px -346px } +.tty_80col .a2c78 { background-position: -55px -372px } +.tty_80col .a2c79 { background-position: -55px -398px } +.tty_80col .a2c80 { background-position: -68px -8px } +.tty_80col .a2c81 { background-position: -68px -34px } +.tty_80col .a2c82 { background-position: -68px -60px } +.tty_80col .a2c83 { background-position: -68px -86px } +.tty_80col .a2c84 { background-position: -68px -112px } +.tty_80col .a2c85 { background-position: -68px -138px } +.tty_80col .a2c86 { background-position: -68px -164px } +.tty_80col .a2c87 { background-position: -68px -190px } +.tty_80col .a2c88 { background-position: -68px -216px } +.tty_80col .a2c89 { background-position: -68px -242px } +.tty_80col .a2c90 { background-position: -68px -268px } +.tty_80col .a2c91 { background-position: -68px -294px } +.tty_80col .a2c92 { background-position: -68px -320px } +.tty_80col .a2c93 { background-position: -68px -346px } +.tty_80col .a2c94 { background-position: -68px -372px } +.tty_80col .a2c95 { background-position: -68px -398px } +.tty_80col.flash .a2c64 { background-position: -159px -8px } +.tty_80col.flash .a2c65 { background-position: -159px -34px } +.tty_80col.flash .a2c66 { background-position: -159px -60px } +.tty_80col.flash .a2c67 { background-position: -159px -86px } +.tty_80col.flash .a2c68 { background-position: -159px -112px } +.tty_80col.flash .a2c69 { background-position: -159px -138px } +.tty_80col.flash .a2c70 { background-position: -159px -164px } +.tty_80col.flash .a2c71 { background-position: -159px -190px } +.tty_80col.flash .a2c72 { background-position: -159px -216px } +.tty_80col.flash .a2c73 { background-position: -159px -242px } +.tty_80col.flash .a2c74 { background-position: -159px -268px } +.tty_80col.flash .a2c75 { background-position: -159px -294px } +.tty_80col.flash .a2c76 { background-position: -159px -320px } +.tty_80col.flash .a2c77 { background-position: -159px -346px } +.tty_80col.flash .a2c78 { background-position: -159px -372px } +.tty_80col.flash .a2c79 { background-position: -159px -398px } +.tty_80col.flash .a2c80 { background-position: -172px -8px } +.tty_80col.flash .a2c81 { background-position: -172px -34px } +.tty_80col.flash .a2c82 { background-position: -172px -60px } +.tty_80col.flash .a2c83 { background-position: -172px -86px } +.tty_80col.flash .a2c84 { background-position: -172px -112px } +.tty_80col.flash .a2c85 { background-position: -172px -138px } +.tty_80col.flash .a2c86 { background-position: -172px -164px } +.tty_80col.flash .a2c87 { background-position: -172px -190px } +.tty_80col.flash .a2c88 { background-position: -172px -216px } +.tty_80col.flash .a2c89 { background-position: -172px -242px } +.tty_80col.flash .a2c90 { background-position: -172px -268px } +.tty_80col.flash .a2c91 { background-position: -172px -294px } +.tty_80col.flash .a2c92 { background-position: -172px -320px } +.tty_80col.flash .a2c93 { background-position: -172px -346px } +.tty_80col.flash .a2c94 { background-position: -172px -372px } +.tty_80col.flash .a2c95 { background-position: -172px -398px } +.tty_80col .a2c96 { background-position: -29px -8px } +.tty_80col .a2c97 { background-position: -29px -34px } +.tty_80col .a2c98 { background-position: -29px -60px } +.tty_80col .a2c99 { background-position: -29px -86px } +.tty_80col .a2c100 { background-position: -29px -112px } +.tty_80col .a2c101 { background-position: -29px -138px } +.tty_80col .a2c102 { background-position: -29px -164px } +.tty_80col .a2c103 { background-position: -29px -190px } +.tty_80col .a2c104 { background-position: -29px -216px } +.tty_80col .a2c105 { background-position: -29px -242px } +.tty_80col .a2c106 { background-position: -29px -268px } +.tty_80col .a2c107 { background-position: -29px -294px } +.tty_80col .a2c108 { background-position: -29px -320px } +.tty_80col .a2c109 { background-position: -29px -346px } +.tty_80col .a2c110 { background-position: -29px -372px } +.tty_80col .a2c111 { background-position: -29px -398px } +.tty_80col .a2c112 { background-position: -42px -8px } +.tty_80col .a2c113 { background-position: -42px -34px } +.tty_80col .a2c114 { background-position: -42px -60px } +.tty_80col .a2c115 { background-position: -42px -86px } +.tty_80col .a2c116 { background-position: -42px -112px } +.tty_80col .a2c117 { background-position: -42px -138px } +.tty_80col .a2c118 { background-position: -42px -164px } +.tty_80col .a2c119 { background-position: -42px -190px } +.tty_80col .a2c120 { background-position: -42px -216px } +.tty_80col .a2c121 { background-position: -42px -242px } +.tty_80col .a2c122 { background-position: -42px -268px } +.tty_80col .a2c123 { background-position: -42px -294px } +.tty_80col .a2c124 { background-position: -42px -320px } +.tty_80col .a2c125 { background-position: -42px -346px } +.tty_80col .a2c126 { background-position: -42px -372px } +.tty_80col .a2c127 { background-position: -42px -398px } +.tty_80col.flash .a2c96 { background-position: -133px -8px } +.tty_80col.flash .a2c97 { background-position: -133px -34px } +.tty_80col.flash .a2c98 { background-position: -133px -60px } +.tty_80col.flash .a2c99 { background-position: -133px -86px } +.tty_80col.flash .a2c100 { background-position: -133px -112px } +.tty_80col.flash .a2c101 { background-position: -133px -138px } +.tty_80col.flash .a2c102 { background-position: -133px -164px } +.tty_80col.flash .a2c103 { background-position: -133px -190px } +.tty_80col.flash .a2c104 { background-position: -133px -216px } +.tty_80col.flash .a2c105 { background-position: -133px -242px } +.tty_80col.flash .a2c106 { background-position: -133px -268px } +.tty_80col.flash .a2c107 { background-position: -133px -294px } +.tty_80col.flash .a2c108 { background-position: -133px -320px } +.tty_80col.flash .a2c109 { background-position: -133px -346px } +.tty_80col.flash .a2c110 { background-position: -133px -372px } +.tty_80col.flash .a2c111 { background-position: -133px -398px } +.tty_80col.flash .a2c112 { background-position: -146px -8px } +.tty_80col.flash .a2c113 { background-position: -146px -34px } +.tty_80col.flash .a2c114 { background-position: -146px -60px } +.tty_80col.flash .a2c115 { background-position: -146px -86px } +.tty_80col.flash .a2c116 { background-position: -146px -112px } +.tty_80col.flash .a2c117 { background-position: -146px -138px } +.tty_80col.flash .a2c118 { background-position: -146px -164px } +.tty_80col.flash .a2c119 { background-position: -146px -190px } +.tty_80col.flash .a2c120 { background-position: -146px -216px } +.tty_80col.flash .a2c121 { background-position: -146px -242px } +.tty_80col.flash .a2c122 { background-position: -146px -268px } +.tty_80col.flash .a2c123 { background-position: -146px -294px } +.tty_80col.flash .a2c124 { background-position: -146px -320px } +.tty_80col.flash .a2c125 { background-position: -146px -346px } +.tty_80col.flash .a2c126 { background-position: -146px -372px } +.tty_80col.flash .a2c127 { background-position: -146px -398px } +.tty_80col.active .a2c64 { background-position: -107px -8px } +.tty_80col.active .a2c65 { background-position: -107px -34px } +.tty_80col.active .a2c66 { background-position: -107px -60px } +.tty_80col.active .a2c67 { background-position: -107px -86px } +.tty_80col.active .a2c68 { background-position: -107px -112px } +.tty_80col.active .a2c69 { background-position: -107px -138px } +.tty_80col.active .a2c70 { background-position: -107px -164px } +.tty_80col.active .a2c71 { background-position: -107px -190px } +.tty_80col.active .a2c72 { background-position: -107px -216px } +.tty_80col.active .a2c73 { background-position: -107px -242px } +.tty_80col.active .a2c74 { background-position: -107px -268px } +.tty_80col.active .a2c75 { background-position: -107px -294px } +.tty_80col.active .a2c76 { background-position: -107px -320px } +.tty_80col.active .a2c77 { background-position: -107px -346px } +.tty_80col.active .a2c78 { background-position: -107px -372px } +.tty_80col.active .a2c79 { background-position: -107px -398px } +.tty_80col.active .a2c80 { background-position: -120px -8px } +.tty_80col.active .a2c81 { background-position: -120px -34px } +.tty_80col.active .a2c82 { background-position: -120px -60px } +.tty_80col.active .a2c83 { background-position: -120px -86px } +.tty_80col.active .a2c84 { background-position: -120px -112px } +.tty_80col.active .a2c85 { background-position: -120px -138px } +.tty_80col.active .a2c86 { background-position: -120px -164px } +.tty_80col.active .a2c87 { background-position: -120px -190px } +.tty_80col.active .a2c88 { background-position: -120px -216px } +.tty_80col.active .a2c89 { background-position: -120px -242px } +.tty_80col.active .a2c90 { background-position: -120px -268px } +.tty_80col.active .a2c91 { background-position: -120px -294px } +.tty_80col.active .a2c92 { background-position: -120px -320px } +.tty_80col.active .a2c93 { background-position: -120px -346px } +.tty_80col.active .a2c94 { background-position: -120px -372px } +.tty_80col.active .a2c95 { background-position: -120px -398px } +.tty_80col.active .a2c96 { background-position: -185px -8px } +.tty_80col.active .a2c97 { background-position: -185px -34px } +.tty_80col.active .a2c98 { background-position: -185px -60px } +.tty_80col.active .a2c99 { background-position: -185px -86px } +.tty_80col.active .a2c100 { background-position: -185px -112px } +.tty_80col.active .a2c101 { background-position: -185px -138px } +.tty_80col.active .a2c102 { background-position: -185px -164px } +.tty_80col.active .a2c103 { background-position: -185px -190px } +.tty_80col.active .a2c104 { background-position: -185px -216px } +.tty_80col.active .a2c105 { background-position: -185px -242px } +.tty_80col.active .a2c106 { background-position: -185px -268px } +.tty_80col.active .a2c107 { background-position: -185px -294px } +.tty_80col.active .a2c108 { background-position: -185px -320px } +.tty_80col.active .a2c109 { background-position: -185px -346px } +.tty_80col.active .a2c110 { background-position: -185px -372px } +.tty_80col.active .a2c111 { background-position: -185px -398px } +.tty_80col.active .a2c112 { background-position: -198px -8px } +.tty_80col.active .a2c113 { background-position: -198px -34px } +.tty_80col.active .a2c114 { background-position: -198px -60px } +.tty_80col.active .a2c115 { background-position: -198px -86px } +.tty_80col.active .a2c116 { background-position: -198px -112px } +.tty_80col.active .a2c117 { background-position: -198px -138px } +.tty_80col.active .a2c118 { background-position: -198px -164px } +.tty_80col.active .a2c119 { background-position: -198px -190px } +.tty_80col.active .a2c120 { background-position: -198px -216px } +.tty_80col.active .a2c121 { background-position: -198px -242px } +.tty_80col.active .a2c122 { background-position: -198px -268px } +.tty_80col.active .a2c123 { background-position: -198px -294px } +.tty_80col.active .a2c124 { background-position: -198px -320px } +.tty_80col.active .a2c125 { background-position: -198px -346px } +.tty_80col.active .a2c126 { background-position: -198px -372px } +.tty_80col.active .a2c127 { background-position: -198px -398px } +.tty_80col .a2c128 { background-position: -55px -8px } +.tty_80col .a2c129 { background-position: -55px -34px } +.tty_80col .a2c130 { background-position: -55px -60px } +.tty_80col .a2c131 { background-position: -55px -86px } +.tty_80col .a2c132 { background-position: -55px -112px } +.tty_80col .a2c133 { background-position: -55px -138px } +.tty_80col .a2c134 { background-position: -55px -164px } +.tty_80col .a2c135 { background-position: -55px -190px } +.tty_80col .a2c136 { background-position: -55px -216px } +.tty_80col .a2c137 { background-position: -55px -242px } +.tty_80col .a2c138 { background-position: -55px -268px } +.tty_80col .a2c139 { background-position: -55px -294px } +.tty_80col .a2c140 { background-position: -55px -320px } +.tty_80col .a2c141 { background-position: -55px -346px } +.tty_80col .a2c142 { background-position: -55px -372px } +.tty_80col .a2c143 { background-position: -55px -398px } +.tty_80col .a2c144 { background-position: -68px -8px } +.tty_80col .a2c145 { background-position: -68px -34px } +.tty_80col .a2c146 { background-position: -68px -60px } +.tty_80col .a2c147 { background-position: -68px -86px } +.tty_80col .a2c148 { background-position: -68px -112px } +.tty_80col .a2c149 { background-position: -68px -138px } +.tty_80col .a2c150 { background-position: -68px -164px } +.tty_80col .a2c151 { background-position: -68px -190px } +.tty_80col .a2c152 { background-position: -68px -216px } +.tty_80col .a2c153 { background-position: -68px -242px } +.tty_80col .a2c154 { background-position: -68px -268px } +.tty_80col .a2c155 { background-position: -68px -294px } +.tty_80col .a2c156 { background-position: -68px -320px } +.tty_80col .a2c157 { background-position: -68px -346px } +.tty_80col .a2c158 { background-position: -68px -372px } +.tty_80col .a2c159 { background-position: -68px -398px } +.tty_80col .a2c160 { background-position: -29px -8px } +.tty_80col .a2c161 { background-position: -29px -34px } +.tty_80col .a2c162 { background-position: -29px -60px } +.tty_80col .a2c163 { background-position: -29px -86px } +.tty_80col .a2c164 { background-position: -29px -112px } +.tty_80col .a2c165 { background-position: -29px -138px } +.tty_80col .a2c166 { background-position: -29px -164px } +.tty_80col .a2c167 { background-position: -29px -190px } +.tty_80col .a2c168 { background-position: -29px -216px } +.tty_80col .a2c169 { background-position: -29px -242px } +.tty_80col .a2c170 { background-position: -29px -268px } +.tty_80col .a2c171 { background-position: -29px -294px } +.tty_80col .a2c172 { background-position: -29px -320px } +.tty_80col .a2c173 { background-position: -29px -346px } +.tty_80col .a2c174 { background-position: -29px -372px } +.tty_80col .a2c175 { background-position: -29px -398px } +.tty_80col .a2c176 { background-position: -42px -8px } +.tty_80col .a2c177 { background-position: -42px -34px } +.tty_80col .a2c178 { background-position: -42px -60px } +.tty_80col .a2c179 { background-position: -42px -86px } +.tty_80col .a2c180 { background-position: -42px -112px } +.tty_80col .a2c181 { background-position: -42px -138px } +.tty_80col .a2c182 { background-position: -42px -164px } +.tty_80col .a2c183 { background-position: -42px -190px } +.tty_80col .a2c184 { background-position: -42px -216px } +.tty_80col .a2c185 { background-position: -42px -242px } +.tty_80col .a2c186 { background-position: -42px -268px } +.tty_80col .a2c187 { background-position: -42px -294px } +.tty_80col .a2c188 { background-position: -42px -320px } +.tty_80col .a2c189 { background-position: -42px -346px } +.tty_80col .a2c190 { background-position: -42px -372px } +.tty_80col .a2c191 { background-position: -42px -398px } +.tty_80col .a2c192 { background-position: -55px -8px } +.tty_80col .a2c193 { background-position: -55px -34px } +.tty_80col .a2c194 { background-position: -55px -60px } +.tty_80col .a2c195 { background-position: -55px -86px } +.tty_80col .a2c196 { background-position: -55px -112px } +.tty_80col .a2c197 { background-position: -55px -138px } +.tty_80col .a2c198 { background-position: -55px -164px } +.tty_80col .a2c199 { background-position: -55px -190px } +.tty_80col .a2c200 { background-position: -55px -216px } +.tty_80col .a2c201 { background-position: -55px -242px } +.tty_80col .a2c202 { background-position: -55px -268px } +.tty_80col .a2c203 { background-position: -55px -294px } +.tty_80col .a2c204 { background-position: -55px -320px } +.tty_80col .a2c205 { background-position: -55px -346px } +.tty_80col .a2c206 { background-position: -55px -372px } +.tty_80col .a2c207 { background-position: -55px -398px } +.tty_80col .a2c208 { background-position: -68px -8px } +.tty_80col .a2c209 { background-position: -68px -34px } +.tty_80col .a2c210 { background-position: -68px -60px } +.tty_80col .a2c211 { background-position: -68px -86px } +.tty_80col .a2c212 { background-position: -68px -112px } +.tty_80col .a2c213 { background-position: -68px -138px } +.tty_80col .a2c214 { background-position: -68px -164px } +.tty_80col .a2c215 { background-position: -68px -190px } +.tty_80col .a2c216 { background-position: -68px -216px } +.tty_80col .a2c217 { background-position: -68px -242px } +.tty_80col .a2c218 { background-position: -68px -268px } +.tty_80col .a2c219 { background-position: -68px -294px } +.tty_80col .a2c220 { background-position: -68px -320px } +.tty_80col .a2c221 { background-position: -68px -346px } +.tty_80col .a2c222 { background-position: -68px -372px } +.tty_80col .a2c223 { background-position: -68px -398px } +.tty_80col .a2c224 { background-position: -81px -8px } +.tty_80col .a2c225 { background-position: -81px -34px } +.tty_80col .a2c226 { background-position: -81px -60px } +.tty_80col .a2c227 { background-position: -81px -86px } +.tty_80col .a2c228 { background-position: -81px -112px } +.tty_80col .a2c229 { background-position: -81px -138px } +.tty_80col .a2c230 { background-position: -81px -164px } +.tty_80col .a2c231 { background-position: -81px -190px } +.tty_80col .a2c232 { background-position: -81px -216px } +.tty_80col .a2c233 { background-position: -81px -242px } +.tty_80col .a2c234 { background-position: -81px -268px } +.tty_80col .a2c235 { background-position: -81px -294px } +.tty_80col .a2c236 { background-position: -81px -320px } +.tty_80col .a2c237 { background-position: -81px -346px } +.tty_80col .a2c238 { background-position: -81px -372px } +.tty_80col .a2c239 { background-position: -81px -398px } +.tty_80col .a2c240 { background-position: -94px -8px } +.tty_80col .a2c241 { background-position: -94px -34px } +.tty_80col .a2c242 { background-position: -94px -60px } +.tty_80col .a2c243 { background-position: -94px -86px } +.tty_80col .a2c244 { background-position: -94px -112px } +.tty_80col .a2c245 { background-position: -94px -138px } +.tty_80col .a2c246 { background-position: -94px -164px } +.tty_80col .a2c247 { background-position: -94px -190px } +.tty_80col .a2c248 { background-position: -94px -216px } +.tty_80col .a2c249 { background-position: -94px -242px } +.tty_80col .a2c250 { background-position: -94px -268px } +.tty_80col .a2c251 { background-position: -94px -294px } +.tty_80col .a2c252 { background-position: -94px -320px } +.tty_80col .a2c253 { background-position: -94px -346px } +.tty_80col .a2c254 { background-position: -94px -372px } +.tty_80col .a2c255 { background-position: -94px -398px } + +.tty_80col .a2c256 { background-position: -211px -8px } +.tty_80col .a2c257 { background-position: -211px -34px } +.tty_80col .a2c258 { background-position: -211px -60px } +.tty_80col .a2c259 { background-position: -211px -86px } +.tty_80col .a2c260 { background-position: -211px -112px } +.tty_80col .a2c261 { background-position: -211px -138px } +.tty_80col .a2c262 { background-position: -211px -164px } +.tty_80col .a2c263 { background-position: -211px -190px } +.tty_80col .a2c264 { background-position: -211px -216px } +.tty_80col .a2c265 { background-position: -211px -242px } +.tty_80col .a2c266 { background-position: -211px -268px } +.tty_80col .a2c267 { background-position: -211px -294px } +.tty_80col .a2c268 { background-position: -211px -320px } +.tty_80col .a2c269 { background-position: -211px -346px } +.tty_80col .a2c270 { background-position: -211px -372px } +.tty_80col .a2c271 { background-position: -211px -398px } +.tty_80col .a2c272 { background-position: -224px -8px } +.tty_80col .a2c273 { background-position: -224px -34px } +.tty_80col .a2c274 { background-position: -224px -60px } +.tty_80col .a2c275 { background-position: -224px -86px } +.tty_80col .a2c276 { background-position: -224px -112px } +.tty_80col .a2c277 { background-position: -224px -138px } +.tty_80col .a2c278 { background-position: -224px -164px } +.tty_80col .a2c279 { background-position: -224px -190px } +.tty_80col .a2c280 { background-position: -224px -216px } +.tty_80col .a2c281 { background-position: -224px -242px } +.tty_80col .a2c282 { background-position: -224px -268px } +.tty_80col .a2c283 { background-position: -224px -294px } +.tty_80col .a2c284 { background-position: -224px -320px } +.tty_80col .a2c285 { background-position: -224px -346px } +.tty_80col .a2c286 { background-position: -224px -372px } +.tty_80col .a2c287 { background-position: -224px -398px } + +/* For non-canvas based hires implementations */ +.hiresPixel { width: 4px; height: 2px; background-color: black; } + +.loresPixel { width: 14px; height: 8px; margin: 0; padding: 0; } +.loresRow { height: 8px; margin: 0; padding: 0; } +.loresDisplay { table-layout: fixed; border-collapse: collapse; } + + + +/* Input Devices */ +.keyboard { width: 1px; height: 1px; border: none; position: absolute; left: -100px; top: -100px; } +td.controlbox { vertical-align: middle; padding-left: 12px; padding-right: 12px; } + +#paddle0, #paddle1 +{ + border-style: inset; + border-width: 2px; + border-color: gray; + background-color: #c0c0c0; + height: 20px; + width: 245px; + text-align: center; +} +#knob0, #knob1 +{ + border-style: outset; + border-width: 2px; + border-color: gray; + background-color: #404040; + height: 16px; + width: 10px; +} + +#joystick +{ + border-style: inset; + border-width: 2px; + border-color: gray; + background-color: #c0c0c0; + width: 100px; + height: 100px; + text-align: center; + vertical-align: middle; + line-height: 100px; +} +#stick +{ + border-style: outset; + border-width: 2px; + border-color: gray; + background-color: #404040; + height: 16px; + width: 16px; +} diff --git a/tty.js b/tty.js new file mode 100644 index 0000000..30bc7e0 --- /dev/null +++ b/tty.js @@ -0,0 +1,904 @@ +// +// Applesoft BASIC in Javascript +// TTY Emulation +// + +// Copyright (C) 2009-2011 Joshua Bell +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Usage: +// +// tty = new TTY( screen_element, keyboard_element, bell ); +// tty.clearScreen() +// tty.scrollScreen() +// tty.setTextStyle( textStyle ) +// { width: w, height: h } = tty.getScreenSize() +// { x: x, y: y } = tty.getCursorPosition() +// tty.setFirmwareActive( bool ) +// tty.setCursorPosition( x, y ) +// tty.showCursor() +// tty.hideCursor() +// tty.focus() +// +// This just calls writeChar() in a loop; no need to hook it +// tty.writeString( string ) +// +// The following can be hooked: +// tty.readLine( callback_function, prompt ) +// tty.readChar( callback_function ) +// tty.writeChar( c ) +// +// tty.TEXT_STYLE_NORMAL = 0 +// tty.TEXT_STYLE_INVERSE = 1 +// tty.TEXT_STYLE_FLASH = 2 +// +// Example: +// +// +// +//
+ +/*global getClassList*/ // from polyfill.js +/*global identifyKey */ // From keyboard.js + +function TTY(screenElement, keyboardElement, bell) { + /*jslint browser: true, white: false, bitwise: false */ + + + // Constants + + + this.TEXT_STYLE_NORMAL = 0; + this.TEXT_STYLE_INVERSE = 1; + this.TEXT_STYLE_FLASH = 2; + + + // Internal Fields + + + // For references to "this" within callbacks and closures + var self = this, + + // Display + cursorX = 0, + cursorY = 0, + cursorVisible = false, + cursorElement = null, + styleElem, + screenGrid, + screenRow = [], + splitPos = 0, + screenWidth, + screenHeight, + curStyle = this.TEXT_STYLE_NORMAL, + cursorState = true, + cursorInterval, + firmwareActive = true, // 80-column firmware + mousetext = false, + + // Input + lineCallback, + charCallback, + inputBuffer = [], + keyboardRegister = 0, + keyDown = false, + capsLock = true, // Caps lock state is tracked unique to the TTY + buttonState = [0, 0, 0, 0]; + + this.autoScroll = true; + + + + // + // Display + // + + function setCellByte(x, y, byte) { + var cell = screenGrid[x + screenWidth * y]; + if (cell && cell.byte !== byte) { + cell.byte = byte; + cell.elem.className = 'a2c a2c' + String(byte); + } + } + + // Apple II Character Generator (byte->character map) + // 0x00-0x1F = INVERSE @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ + // 0x20-0x3F = INVERSE !"#$%&'()*+,-./0123456789:;<=>? + // 0x40-0x5F = FLASH @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ (80-col firmware active: mousetext symbols) + // 0x60-0x7F = FLASH !"#$%&'()*+,-./0123456789:;<=>? (80-col firmware active: inverse lowercase) + // 0x80-0x9F = NORMAL @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ + // 0xA0-0xBF = NORMAL !"#$%&'()*+,-./0123456789:;<=>? + // 0xC0-0xDF = NORMAL @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ + // 0xE0-0xFF = NORMAL `abcdefghijklmnopqrstuvwxyz{|}~ + + + function setCellChar(x, y, c) { + var byte; + + if (c > 0xff) { + // Extension characters + byte = c; + } else { + // Lock to 7-bit; Control characters should be filtered already + c = (c >>> 0) & 0x7f; + + if (firmwareActive) { + if (curStyle === self.TEXT_STYLE_INVERSE) { + if (0x20 <= c && c < 0x40) { byte = c; } + else if (0x40 <= c && c < 0x60) { byte = c - (mousetext ? 0 : 0x40); } + else if (0x60 <= c && c < 0x80) { byte = c; } + } else if (curStyle === self.TEXT_STYLE_FLASH) { + if (0x20 <= c && c < 0x40) { byte = c + 0x40; } + else if (0x40 <= c && c < 0x60) { byte = c - 0x40; } + else if (0x60 <= c && c < 0x80) { byte = c; } + } else { + if (0x20 <= c && c < 0x40) { byte = c + 0x80; } + else if (0x40 <= c && c < 0x60) { byte = c + 0x80; } + else if (0x60 <= c && c < 0x80) { byte = c + 0x80; } + } + } else { + if (curStyle === self.TEXT_STYLE_INVERSE) { + if (0x20 <= c && c < 0x40) { byte = c; } + else if (0x40 <= c && c < 0x60) { byte = c - 0x40; } + else if (0x60 <= c && c < 0x80) { byte = c - 0x40; } // no inverse lowercase + } else if (curStyle === self.TEXT_STYLE_FLASH) { + if (0x20 <= c && c < 0x40) { byte = c + 0x40; } + else if (0x40 <= c && c < 0x60) { byte = c; } + else if (0x60 <= c && c < 0x80) { byte = c; } // no lowercase flash + } else { + if (0x20 <= c && c < 0x40) { byte = c + 0x80; } + else if (0x40 <= c && c < 0x60) { byte = c + 0x80; } + else if (0x60 <= c && c < 0x80) { byte = c + 0x80; } + } + } + } + setCellByte(x, y, byte); + } + + this.reset = function _reset() { + this.hideCursor(); + lineCallback = undefined; + charCallback = undefined; + + inputBuffer = []; + keyboardRegister = 0; + buttonState = [0, 0, 0, 0]; + + }; // reset + + function init(active, rows, columns) { + firmwareActive = active; + screenWidth = columns; + screenHeight = rows; + + // Reset parameters + self.textWindow = {}; + self.textWindow.left = 0; + self.textWindow.top = 0; + self.textWindow.width = screenWidth; + self.textWindow.height = screenHeight; + self.setTextStyle(self.TEXT_STYLE_NORMAL); + + // Build character cell grid + var x, y, table, tbody, tr, td; + screenGrid = []; + screenGrid.length = screenWidth * screenHeight; + + table = document.createElement('table'); + table.className = 'tty_table'; + + tbody = document.createElement('tbody'); + styleElem = tbody; + + getClassList(styleElem).add(screenWidth === 40 ? 'tty_40col' : 'tty_80col'); + if (firmwareActive) { getClassList(styleElem).add('active'); } + + for (y = 0; y < screenHeight; y += 1) { + tr = document.createElement('tr'); + tr.className = 'tty_tr'; + tr.style.visibility = (y < splitPos) ? "hidden" : ""; + screenRow[y] = tr; + + for (x = 0; x < screenWidth; x += 1) { + td = document.createElement('td'); + screenGrid[screenWidth * y + x] = { + elem: td + }; + tr.appendChild(td); + } + + tbody.appendChild(tr); + } + table.appendChild(tbody); + screenElement.innerHTML = ""; + screenElement.appendChild(table); + + self.clearScreen(); + + // Create cursor + cursorElement = document.createElement('span'); + cursorElement.className = 'a2c a2c-cursor a2c255'; + self.setCursorPosition(0, 0); + } + + this.clearScreen = function _clearScreen() { + var x, y; + cursorX = self.textWindow.left; + cursorY = self.textWindow.top; + for (y = self.textWindow.top; y < self.textWindow.top + self.textWindow.height; y += 1) { + for (x = self.textWindow.left; x < self.textWindow.left + self.textWindow.width; x += 1) { + setCellChar(x, y, 0x20); + } + } + }; + + + this.clearEOL = function _clearEOL() { + var x; + for (x = cursorX; x < self.textWindow.left + self.textWindow.width; x += 1) { + setCellChar(x, cursorY, 0x20); + } + }; + + + this.setFirmwareActive = function _setFirmwareActive(active) { + init(active, 24, active ? 80 : 40); + }; + + + function scrollUp() { + var x, y, cell; + + for (y = self.textWindow.top; y < self.textWindow.top + self.textWindow.height - 1; y += 1) { + for (x = self.textWindow.left; x < self.textWindow.left + self.textWindow.width; x += 1) { + + cell = screenGrid[x + screenWidth * (y + 1)]; + setCellByte(x, y, cell.byte); + } + } + + y = self.textWindow.top + (self.textWindow.height - 1); + for (x = self.textWindow.left; x < self.textWindow.left + self.textWindow.width; x += 1) { + setCellChar(x, y, 0x20); + } + } + + function scrollDown() { + var x, y, cell; + + for (y = self.textWindow.top + self.textWindow.height - 1; y > self.textWindow.top; y -= 1) { + for (x = self.textWindow.left; x < self.textWindow.left + self.textWindow.width; x += 1) { + + cell = screenGrid[x + screenWidth * (y - 1)]; + setCellByte(x, y, cell.byte); + } + } + + y = self.textWindow.top; + for (x = self.textWindow.left; x < self.textWindow.left + self.textWindow.width; x += 1) { + setCellChar(x, y, 0x20); + } + } + + this.scrollScreen = function _scrollScreen() { + scrollUp(); + }; + + this.setTextStyle = function _setTextStyle(style) { + curStyle = style; + }; + + // Internal + function updateCursor() { + if (cursorVisible && cursorState) { + var elem = screenGrid[cursorY * screenWidth + cursorX].elem; + if (elem !== cursorElement.parentNode) { + elem.appendChild(cursorElement); + } + } else if (cursorElement.parentNode) { + cursorElement.parentNode.removeChild(cursorElement); + } + } + + // Internal + function lineFeed() { + cursorY += 1; + if (cursorY >= self.textWindow.top + self.textWindow.height) { + cursorY = self.textWindow.top + self.textWindow.height - 1; + + if (self.autoScroll) { + self.scrollScreen(); + } + } + + updateCursor(); + } + + // Internal + function advanceCursor() { + // Advance the cursor + cursorX += 1; + + if (cursorX >= self.textWindow.left + self.textWindow.width) { + cursorX = self.textWindow.left; + lineFeed(); + } + + updateCursor(); + } + + // Hookable + this.writeChar = function _writeChar(c) { + var code = c.charCodeAt(0), + x, y; + + switch (code) { + case 0: + case 1: + case 2: + case 3: + case 4: // DOS hook takes care of CHR$(4) + case 5: + case 6: + // no-op + break; + + case 7: // (BEL) bell + if (bell) { + bell(); + } + break; + + case 8: // (BS) backspace + cursorX -= 1; + if (cursorX < self.textWindow.left) { + cursorX += self.textWindow.width; + cursorY -= 1; + if (cursorY < self.textWindow.top) { + cursorY = self.textWindow.top; + } + } + break; + + case 9: + break; + + case 10: // (LF) line feed + lineFeed(); + break; + + case 11: // (VT) clear EOS + if (firmwareActive) { + // Clears from the cursor position to the end of the window + for (x = cursorX; x < self.textWindow.left + self.textWindow.width; x += 1) { + setCellChar(x, cursorY, 0x20); + } + for (y = cursorY + 1; y < self.textWindow.top + self.textWindow.height; y += 1) { + for (x = self.textWindow.left; x < self.textWindow.left + self.textWindow.width; x += 1) { + setCellChar(x, y, 0x20); + } + } + } + break; + + case 12: // (FF) clear + if (firmwareActive) { + // move cursor to upper left and clear window + self.clearScreen(); + } + break; + + case 13: // (CR) return + cursorX = self.textWindow.left; + lineFeed(); + break; + + case 14: // (SO) normal + if (firmwareActive) { + curStyle = self.TEXT_STYLE_NORMAL; + } + break; + + case 15: // (SI) inverse + if (firmwareActive) { + curStyle = self.TEXT_STYLE_INVERSE; + } + break; + + case 16: + break; + + case 17: // (DC1) 40-column + if (firmwareActive) { + // set display to 40 columns + init(true, 24, 40); + } + break; + + case 18: // (DC2) 80-column + if (firmwareActive) { + // set display to 80 columns + init(true, 24, 80); + } + break; + + case 19: // (DC3) stop list + case 20: + break; + + case 21: // (NAK) quit + if (firmwareActive) { + // deactivate, home, clear screen + init(false, 24, 40); + } + break; + + case 22: // (SYN) scroll down + if (firmwareActive) { + // scroll display down, leaving cursor + scrollDown(); + } + break; + + case 23: // (ETB) scroll up + if (firmwareActive) { + // scroll display up, leaving cursor + scrollUp(); + } + break; + + case 24: // (CAN) disable mousetext + if (firmwareActive) { + // http://www.umich.edu/~archive/apple2/technotes/tn/mous/TN.MOUS.006 + mousetext = false; + } + break; + + case 25: // (EM) home + if (firmwareActive) { + // Moves cursor to upper-left corner of window (but doesn't clear) + cursorX = self.textWindow.left; + cursorY = self.textWindow.top; + } + break; + + case 26: // (SUB) clear line + if (firmwareActive) { + // Clears the line the cursor position is on + for (x = 0; x < self.textWindow.width; x += 1) { + setCellChar(self.textWindow.left + x, cursorY, 0x20); + } + } + break; + + case 27: // (ESC) enable mousetext + if (firmwareActive) { + // http://www.umich.edu/~archive/apple2/technotes/tn/mous/TN.MOUS.006 + mousetext = true; + } + break; + + case 28: // (FS) fwd. space + if (firmwareActive) { + // Moves cursor position one space to the right; from right edge + // of window, moves it to left end of line below + cursorX += 1; + if (cursorX > (self.textWindow.left + self.textWindow.width)) { + cursorX -= self.textWindow.width; + cursorY += 1; + if (cursorY > self.textWindow.top + self.textWindow.height) { + cursorY = self.textWindow.top + self.textWindow.height; + } + } + } + break; + + case 29: // (GS) clear EOL + if (firmwareActive) { + // Clear line rom cursor position to the right edge of the window + self.clearEOL(); + } + break; + + case 30: // RS - gotoXY (not supported from BASIC) + case 31: + break; + + default: + setCellChar(cursorX, cursorY, code); + advanceCursor(); + break; + } + }; + + // Hookable + this.writeString = function _writeString(s) { + var i; + for (i = 0; i < s.length; i += 1) { + this.writeChar(s.charAt(i)); + } + }; + + this.getScreenSize = function _getScreenSize() { + return { width: screenWidth, height: screenHeight }; + }; + + this.getCursorPosition = function _getCursorPosition() { + return { x: cursorX, y: cursorY }; + }; + + this.setCursorPosition = function _setCursorPosition(x, y) { + if (x !== undefined) { + x = Math.min(Math.max(Math.floor(x), 0), screenWidth - 1); + } else { + x = cursorX; + } + + if (y !== undefined) { + y = Math.min(Math.max(Math.floor(y), 0), screenHeight - 1); + } else { + y = cursorY; + } + + if (x === cursorX && y === cursorY) { + // no-op + return; + } + + cursorX = x; + cursorY = y; + updateCursor(); + }; + + this.showCursor = function _showCursor() { + cursorVisible = true; + cursorInterval = setInterval(function() { + cursorState = !cursorState; + updateCursor(); + }, 500); + }; + + this.hideCursor = function _hideCursor() { + clearInterval(cursorInterval); + cursorVisible = false; + updateCursor(); + + }; + + this.splitScreen = function _splitScreen(splitAt) { + splitPos = splitAt; + + var y; + + for (y = 0; y < screenHeight; y += 1) { + screenRow[y].style.visibility = (y < splitPos) ? "hidden" : ""; + } + + }; + + + // + // Input + // + + + // Internal + function onKey(code) { + var cb, c, s; + + keyboardRegister = code | 0x80; + + if (charCallback) { + keyboardRegister = keyboardRegister & 0x7f; + + cb = charCallback; + charCallback = undefined; + self.hideCursor(); + cb(String.fromCharCode(code)); + } else if (lineCallback) { + keyboardRegister = keyboardRegister & 0x7f; + + if (code >= 32 && code <= 127) { + c = String.fromCharCode(code); + inputBuffer.push(c); + self.writeChar(c); // echo + } else { + switch (code) { + case 8: // Left Arrow + if (inputBuffer.length > 0) { + inputBuffer.pop(); + self.setCursorPosition(Math.max(self.getCursorPosition().x - 1, 0), self.getCursorPosition().y); + } + break; + + case 13: // Enter + // Respond to INPUT callback, if defined + s = inputBuffer.join(""); + inputBuffer = []; + self.writeString("\r"); + + cb = lineCallback; + lineCallback = undefined; + self.hideCursor(); + cb(s); + break; + } + } + } + // else: nothing - key stays in the keyboard register + + } // onKey + + function toAppleKey(e) { + + function ord(c) { return c.charCodeAt(0); } + + switch (e.keyName) { + + // Non-Printables + case 'Backspace': return 127; + case 'Tab': return 9; // NOTE: Blocked elsewhere, for web page accessibility + case 'Enter': return 13; + case 'Escape': return 27; + case 'Left': return 8; + case 'Up': return 11; + case 'Right': return 21; + case 'Down': return 10; + case 'Delete': return 127; + case 'Clear': return 24; // ctrl-X - used on the IIgs + + // Numeric + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (e.location === KeyboardEvent.DOM_KEY_LOCATION_NUMPAD) { + // Numpad, presumably - allow but nothing special + return ord(e.keyName); + } else if (e.ctrlKey) { + if (e.shiftKey) { + switch (e.keyName) { + case '2': return 0; // ctrl-@ + case '6': return 30; // ctrl-^ + } + } + return; + } else if (e.shiftKey) { + return ')!@#$%^&*('.charCodeAt(ord(e.keyName) - ord('0')); + } else { + return ord(e.keyName); + } + + // Alphabetic + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + if (e.ctrlKey) { + return ord(e.keyName) - 64; // Control keys, Apple II-style + } else if (capsLock || e.shiftKey) { + return ord(e.keyName); // Upper case + } else { + return ord(e.keyName) + 32; // Lower case + } + + // Symbol and Punctuation + case 'Spacebar': return ord(' '); + case 'Semicolon': return e.shiftKey ? ord(':') : ord(';'); + case 'Equals': return e.shiftKey ? ord('+') : ord('='); + case 'Comma': return e.shiftKey ? ord('<') : ord(','); + case 'Minus': return e.ctrlKey ? 31 : e.shiftKey ? ord('_') : ord('-'); + case 'Period': return e.shiftKey ? ord('>') : ord('.'); + case 'Solidus': return e.shiftKey ? ord('?') : ord('/'); + case 'Grave': return e.shiftKey ? ord('~') : ord('`'); + case 'LeftSquareBracket': return e.ctrlKey ? 27 : e.shiftKey ? ord('{') : ord('['); + case 'Backslash': return e.ctrlKey ? 28 : e.shiftKey ? ord('|') : ord('\\'); + case 'RightSquareBracket': return e.ctrlKey ? 29 : e.shiftKey ? ord('}') : ord(']'); + case 'Apostrophe': return e.shiftKey ? ord('"') : ord('\''); + + // not present on Apple II keyboard + default: + break; + } + + return -1; + } + + function isBrowserKey(e) { + return e.keyName === 'Tab' || e.keyName === 'F5' || e.metaKey; + } + + + // Internal + function handleKeyDown(e) { + identifyKey(e); + + if (!e.keyName || isBrowserKey(e)) { + return true; + } + + var handled = false, code; + + switch (e.keyName) { + + case 'CapsLock': + capsLock = !capsLock; + handled = true; + break; + + // Used as paddle buttons (0=Open Apple, 1=Solid Apple) + case 'Home': buttonState[0] = 255; handled = true; break; + case 'End': buttonState[1] = 255; handled = true; break; + case 'PageUp': buttonState[2] = 255; handled = true; break; + case 'Shift': buttonState[2] = 255; handled = true; break; + case 'PageDown': buttonState[3] = 255; handled = true; break; + + default: + code = toAppleKey(e); + if (code !== -1) { + keyDown = true; + onKey(code); + handled = true; + } + break; + } + + if (handled) { + e.stopPropagation(); + e.preventDefault(); + } + + return !handled; + } + + + // Internal + function handleKeyUp(e) { + identifyKey(e); + + if (!e.keyName || isBrowserKey(e)) { + return true; + } + + var handled = false, + code; + + switch (e.keyName) { + + case 'CapsLock': + handled = true; + break; + + // Used as paddle buttons (0=Open Apple, 1=Solid Apple) + case 'Home': buttonState[0] = 0; handled = true; break; + case 'End': buttonState[1] = 0; handled = true; break; + case 'PageUp': buttonState[2] = 0; handled = true; break; + case 'Shift': buttonState[2] = 0; handled = true; break; + case 'PageDown': buttonState[3] = 0; handled = true; break; + + default: + code = toAppleKey(e); + if (code !== -1) { + keyDown = false; + handled = true; + } + break; + } + + if (handled) { + e.stopPropagation(); + e.preventDefault(); + } + + return !handled; + } + + + this.getButtonState = function _getButtonState(btn) { + return buttonState[btn]; + }; + + + this.focus = function _focus() { + keyboardElement.focus(); + }; + + + // Hookable + this.readLine = function _readLine(callback, prompt) { + self.writeString(prompt); + + lineCallback = callback; + self.showCursor(); + self.focus(); + }; + + + // Hookable + this.readChar = function _readChar(callback) { + // If there is a key ready, deliver it immediately + if (keyboardRegister & 0x80) { + keyboardRegister = keyboardRegister & 0x7f; + + // Non-blocking return + setTimeout(function() { callback(String.fromCharCode(keyboardRegister)); }, 0); + } else { + charCallback = callback; + self.showCursor(); + self.focus(); + } + }; + + + this.getKeyboardRegister = function _getKeyboardRegister() { + return keyboardRegister; + }; + + + this.clearKeyboardStrobe = function _clearKeyboardStrobe() { + keyboardRegister = keyboardRegister & 0x7f; + return keyboardRegister | (keyDown ? 0x80 : 0x00); + }; + + + // + // Constructor Logic + // + + + init(false, 24, 40); + + window.addEvent(keyboardElement, 'keydown', handleKeyDown); + window.addEvent(keyboardElement, 'keyup', handleKeyUp); + + setInterval(function _blinkFlash() { + window.getClassList(styleElem).toggle('flash'); + }, 250); +} + + diff --git a/vfs/DATAFILE.txt b/vfs/DATAFILE.txt new file mode 100644 index 0000000..94e7887 --- /dev/null +++ b/vfs/DATAFILE.txt @@ -0,0 +1,26 @@ +0123456789ABCDEFGHJKLMNPQRSTUVWXYZ +INDEPENDENT +NAVY +SCOUT +MERCHANT +TRADER +COURIER +SURVEY +TRADER +TRANSPORT +XBOAT +0.3 +0.4 +0.5 +0.7 +0.8 +0.9 +1.0 +1.1 +1.2 +1.3 +1.5 +1.7 +2.0 +3.0 +4.0 diff --git a/vfs/JABBERWOCKY.txt b/vfs/JABBERWOCKY.txt new file mode 100644 index 0000000..a0e0405 --- /dev/null +++ b/vfs/JABBERWOCKY.txt @@ -0,0 +1,4 @@ +Twas brillig and the slithy toves +Did gyre and gimble in the wabe +All mimsy were the borogoves +And mome raths outgrabe diff --git a/vfs/OD JUMP.txt b/vfs/OD JUMP.txt new file mode 100644 index 0000000..608c835 --- /dev/null +++ b/vfs/OD JUMP.txt @@ -0,0 +1,169 @@ +9 +8 +8 +7 +7 +6 +6 +6 +7 +7 +8 +8 +9 +8 +7 +7 +6 +6 +5 +5 +5 +6 +6 +7 +7 +8 +7 +6 +6 +5 +5 +4 +4 +4 +5 +5 +6 +6 +7 +6 +5 +5 +4 +4 +3 +3 +3 +4 +4 +5 +5 +6 +6 +5 +4 +3 +3 +2 +2 +2 +3 +3 +4 +5 +6 +6 +5 +4 +3 +2 +1 +1 +1 +2 +3 +4 +5 +6 +6 +5 +4 +3 +2 +1 +0 +1 +2 +3 +4 +5 +6 +6 +5 +4 +3 +2 +2 +1 +2 +2 +3 +4 +5 +6 +6 +5 +4 +4 +3 +3 +2 +3 +3 +4 +4 +5 +6 +6 +6 +5 +5 +4 +4 +3 +4 +4 +5 +5 +6 +6 +7 +7 +6 +6 +5 +5 +4 +5 +5 +6 +6 +7 +7 +8 +8 +7 +7 +6 +6 +5 +6 +6 +7 +7 +8 +8 +9 +9 +8 +8 +7 +7 +6 +7 +7 +8 +8 +9 +9 diff --git a/vfs/SHIPS.txt b/vfs/SHIPS.txt new file mode 100644 index 0000000..f4bd44f --- /dev/null +++ b/vfs/SHIPS.txt @@ -0,0 +1,28 @@ +26 + A 0200 111 10 20 0082 0030 S 7 4 015000 037.080 04 BEOWULF FREE TRADER IM 240 + A 0200 111 10 20 0082 0030 S 7 4 015000 037.080 04 FANCY FREE FREE TRADER DA 240 + A 0200 111 10 20 0082 0030 S 7 4 015000 037.080 04 FAST BUCK FREE TRADER NA 240 + A 0200 111 10 20 0082 0030 S 7 4 015000 037.080 04 SWORD OF LIGHT FREE TRADER SW 240 + C 0800 333 25 00 0080 318 U 5 1 041700 445.950 10 BROADSWORD MERC CRUISER IM P + C 0800 333 25 00 0080 318 U 6 1 041700 445.950 10 HALBERD MERC CRUISER IM P + E 0400 347 12 04 0010 0200 U 5 1 036000 355.990 12 GAZELLE CLOSE ESCORT IM P + E 0400 347 12 04 0010 0200 U 5 1 036000 355.990 12 UNICORN CLOSE ESCORT IM P + F 0200 212 13 09 0061 0050 S 7 4 016250 066.175 03 EMPRESS NICHOLLE FAR TRADER IM 240 + F 0200 212 13 09 0061 0050 S 7 4 016250 066.175 03 REGENT ARBELLATR FAR TRADER IM 240 + I 5000 111 15 00 2911 0510 S 7 3 047400 985.200 15 BROBDINGNAG BULK CARRIER IM 240 + K 0200 212 11 00 0016 0060 S 0 0 020000 081.080 05 RAINWOLF SAFARI SHIP IM 240 + K 0200 212 11 00 0030 0060 S 7 4 015750 081.080 03 BUSH RUNNER SAFARI SHIP CONV IM 240 + L 0400 212 20 00 0118 0090 U 7 4 028700 158.980 07 RING OF STEEL LAB SHIP CONVERT IM 240 + L 0400 212 20 00 0118 0090 U 8 4 028700 158.980 07 MUAN IWN LAB SHIP CONVERT VE 240 + M 0600 313 30 20 0129 0210 U 7 4 034700 236.970 09 AD ASTRA SUB LINER IM S + M 0600 313 30 20 0129 0210 U 7 4 034700 236.970 09 CYNGUS SUB LINER IM S + N 3000 414 25 00 1329 1240 U 8 3 050700 809.010 15 GOLDEN HARVEST LONG FREIGHTER IM 240 + N 3000 414 25 00 1329 1240 U 7 4 050700 809.010 15 SAFETY FIRST LONG FREIGHTER IM 240 + O 1000 414 50 00 0130 0440 S 8 3 052700 526.400 15 DENEB EXPRESS LONG LINER IM 240 + O 1000 414 50 00 0130 0440 S 8 3 052700 526.400 15 MORA BOUND LONG LINER IM 240 + R 0400 111 13 09 0210 0050 S 7 4 020000 101.030 05 CHAIN SAW FAT TRADER DA 240 + R 0400 111 13 09 0210 0050 S 7 4 020000 101.030 05 MARCH HARRIER FAT TRADER IM S + S 0100 222 04 00 0003 0040 S 5 2 007500 029.430 01 DAFFODIL SCOUT/COURIER IM P + S 0100 222 04 00 0003 0040 S 6 2 007500 029.430 01 BLACK ORCHID SCOUT/COURIER IM P + X 0100 404 02 00 0001 0040 U 9 2 007500 070.65 01 X-51216 EXPRESS BOAT IM P + \ No newline at end of file diff --git a/vfs/SHIPS@.txt b/vfs/SHIPS@.txt new file mode 100644 index 0000000..466cbf8 --- /dev/null +++ b/vfs/SHIPS@.txt @@ -0,0 +1,39 @@ +17 +26 +99 +TYPE CODE +1 +TONNAGE +4 +PERFORMANC +3 +STATEROOMS +2 +LOW BERTHS +2 +CARGO HOLD +4 +FUEL +4 +STREAMLINE +1 +SHIP NATUR +1 +SHIP SERVI +1 +SALARIES +6 +SHIP COST +7 +CREW +2 +NAME +16 +SHIP TYPE +16 +ALLEGIANCE +2 +PAYMENTS +3 +FIELD 18 +5 diff --git a/vfs/SOLOMANI.txt b/vfs/SOLOMANI.txt new file mode 100644 index 0000000000000000000000000000000000000000..fbb6a11762cde6e6d3717662eb0416f073a4aabb GIT binary patch literal 20795 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 aZzlt2PB9i+$n`J*{alY)&oSo>g@OKT{S;PJ; zcvtxRO6O~({a$%H?uDIIj&G6gP5hhsZFqOs?vCvHJM7oS&L)mc96N1)7w3s%m;Kzt zafss#`*DW-J=j0w|B&~Cy+i&_+OLD2PTJl{`0(eX?OyVKiR+@Lo6h6q-X)%kE-yTn zyj}Eksqdo>k2oH79(Er2dtp0|xL&xayps$bB(&dY{e}9x?U!{H<@qFZ z90hM>&xa`TROG4Bd}Vz{d9DcUM-k5?j_JNqm^}}Kwlm4sjPA>r#KByMiJj>>$D|&b z3+?~J9&;fUaV_jD>b0mB^C6b|SZIG1aWDK?__5H*@|=#9uG^xHtE>afk@jbi=T(kp zdA%en}>!3sCL@+0U`49(PANUUb9rAam*QH*U zdfjkb%!#=8d(nsHM#s&(h>Omz_d#e*v|cZEANpo41am=X-D^HH-=hwi2YsJ@5B0mB zy=QWmPdLBt)jq9PVe<*Q&xKuQVdr1%)$>KzIudpt37bEM>nb#l21N4*cG&aDo)`8U zN;R_2IX|h!^z$E&>yY8ODQumj`urPr>P4SdU;CN+iJys|$^CR*)$XlBt^KZ-(D4-U zv#+x}NA-8Wd7xi)-SJJ&Z#_F-^r@bGe!|QC&PlwJ{Hl-JfBHD5=b!AFPyZAA-MUEj zx3K4d(D`5FVZl#-ruwtV3dZ<7Bo_=C~C;MAyKK6G$?+c-I|ER}9_s?@X cwWrPN|Di=63tI=mj!W2j(BIS6jZnP*0fc>FX8-^I literal 0 HcmV?d00001 diff --git a/vfs/SPINWARD.txt b/vfs/SPINWARD.txt new file mode 100644 index 0000000000000000000000000000000000000000..35226e4852a51e168d6ac5da97c09f68714436dd GIT binary patch literal 22235 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 literal 0 HcmV?d00001