From f611c09428987526eafe473cf76866904cf729e6 Mon Sep 17 00:00:00 2001 From: Will Scullin Date: Sat, 5 Aug 2023 18:55:45 -0700 Subject: [PATCH] Convert canvas to Typescript --- js/canvas1.js | 221 ----------------------------------------------- js/canvas1.ts | 232 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+), 221 deletions(-) delete mode 100644 js/canvas1.js create mode 100644 js/canvas1.ts diff --git a/js/canvas1.js b/js/canvas1.js deleted file mode 100644 index 9c3498d..0000000 --- a/js/canvas1.js +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright 2010-2019Will Scullin - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -import { charset } from './roms/apple1char'; - -/* -0: A9 9 AA 20 EF FF E8 8A 4C 2 0 -0R -*/ - -/* - * Text Page Drawing - */ - -export function TextPage() -{ - var _page; - var _context; - - var _buffer = []; - var _greenMode = false; - var _scanlines = false; - - var _black = [0x00,0x00,0x00]; - var _white = [0xee,0xff,0xff]; - var _green = [0x00,0xff,0x80]; - var _blinking = 0; - - var _row = 0; - var _col = 0; - var _dirty = false; - - function _init() { - _buffer = []; - for (var row = 0; row < 24; row++) { - _buffer[row] = []; - for (var col = 0; col < 40; col++) { - _buffer[row][col] = col % 2 ? 0x00 : 0xff; - } - } - _dirty = true; - } - - _init(); - - return { - init: function() { - var self = this; - window.setInterval(function() { - _blinking = (_blinking + 1) % 3; - self._blink(); - _dirty = true; - }, 333); - }, - - write: function(val) { - var col; - val &= 0x7f; - - if (this.transcript) { - if (val == 0xd) { - this.transcript += '\n'; - } else if (val >= 0x20) { - if (val >= 0x60) { - val &= 0x5f; - } - this.transcript += String.fromCharCode(val); - } - } - - if (val == 0x0d) { - for (col = _col; col < 40; col++) { - _buffer[_row][col] = 0x20; - } - _col = 0; - _row++; - } else { - _buffer[_row][_col] = val; - _col++; - if (_col > 39) { - _col = 0; - _row++; - } - } - if (_row > 23) { - _row = 23; - _buffer.shift(); - _buffer.push([]); - for (col = 0; col < 40; col++) { - _buffer[_row][col] = 0x20; - } - } - _buffer[_row][_col] = 0x00; - this.refresh(); - }, - writeAt: function(row, col, val) { - _buffer[row][col] = val; - var data = _page.data, fore, back, color; - var off = (col * 14 + row * 560 * 8 * 2) * 4; - - fore = _greenMode ? _green : _white; - back = _black; - var char = 0; - - if (!val) { - if (_blinking) { - fore = _black; - } - } else { - char = val & 0x1f; - char |= val & 0x40 ? 0 : 0x20; - } - - for (var jdx = 0; jdx < 8; jdx++) { - var b = charset[char * 8 + jdx]; - for (var idx = 0; idx < 7; idx += 1) { - b <<= 1; - color = (b & 0x80) ? fore : back; - var c0 = color[0], c1 = color[1], c2 = color[2]; - data[off + 0] = data[off + 4] = c0; - data[off + 1] = data[off + 5] = c1; - data[off + 2] = data[off + 6] = c2; - if (!_scanlines) { - data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0; - data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1; - data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2; - } else { - data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0 >> 1; - data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1 >> 1; - data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2 >> 1; - } - off += 8; - } - off += 546 * 4 + 560 * 4; - } - }, - _blink: function() { - for (var row = 0; row < 24; row++) { - for (var col = 0; col < 40; col++) { - var val = _buffer[row][col]; - if (!val) { - this.writeAt(row, col, val); - } - } - } - _dirty = true; - }, - refresh: function() { - for (var row = 0; row < 24; row++) { - for (var col = 0; col < 40; col++) { - this.writeAt(row, col, _buffer[row][col]); - } - } - _dirty = true; - }, - green: function(on) { - _greenMode = on; - this.refresh(); - }, - scanlines: function(on) { - _scanlines = on; - this.refresh(); - }, - blit: function() { - if (_dirty) { - _context.putImageData(_page, 0, 0, 0, 0, 7 * 40 * 2, 8 * 24 * 2); - } - }, - setContext: function(context) { - _context = context; - _page = context.createImageData(560, 384); - for (var idx = 0; idx < 560 * 384 * 4; idx++) { - _page.data[idx] = 0xff; - } - }, - getText: function() { - function mapCharCode(charCode) { - charCode &= 0x7F; - if (charCode < 0x20) { - charCode += 0x40; - } - if (charCode >= 0x60) { - charCode -= 0x40; - } - return charCode; - } - - var buffer = '', line, charCode; - var row, col; - for (row = 0; row < 24; row++) { - line = ''; - for (col = 0; col < 40; col++) { - charCode = mapCharCode(_buffer[row][col]); - line += String.fromCharCode(charCode); - } - line = line.trimRight(); - buffer += line + '\n'; - } - return buffer; - }, - clear: function canvas_clearScreen() { - for (var row = 0; row < 24; row++) { - for (var col = 0; col < 40; col++) { - _buffer[row][col] = 0x20; - } - } - _col = 0; - _row = 0; - this.refresh(); - }, - transcript: '' - }; -} diff --git a/js/canvas1.ts b/js/canvas1.ts new file mode 100644 index 0000000..64a2616 --- /dev/null +++ b/js/canvas1.ts @@ -0,0 +1,232 @@ +/* Copyright 2010-2023 Will Scullin + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +import { charset } from "./roms/apple1char"; +import type { byte } from "./types"; + +/* +0: A9 9 AA 20 EF FF E8 8A 4C 2 0 +0R +*/ + +/* + * Text Page Drawing + */ + +export class TextPage { + _page: ImageData; + _context: CanvasRenderingContext2D; + + _buffer: byte[][] = []; + _greenMode = false; + _scanlines = false; + + _black = [0x00, 0x00, 0x00]; + _white = [0xee, 0xff, 0xff]; + _green = [0x00, 0xff, 0x80]; + _blinking = 0; + + _row = 0; + _col = 0; + _dirty = false; + + constructor() { + this._buffer = []; + for (var row = 0; row < 24; row++) { + this._buffer[row] = []; + for (var col = 0; col < 40; col++) { + this._buffer[row][col] = col % 2 ? 0x00 : 0xff; + } + } + this._dirty = true; + } + + init() { + window.setInterval(() => { + this._blinking = (this._blinking + 1) % 3; + this._blink(); + this._dirty = true; + }, 333); + } + + write(val: byte): void { + var col; + val &= 0x7f; + + if (this.transcript) { + if (val == 0xd) { + this.transcript += "\n"; + } else if (val >= 0x20) { + if (val >= 0x60) { + val &= 0x5f; + } + this.transcript += String.fromCharCode(val); + } + } + + if (val == 0x0d) { + for (col = this._col; col < 40; col++) { + this._buffer[this._row][col] = 0x20; + } + this._col = 0; + this._row++; + } else { + this._buffer[this._row][this._col] = val; + this._col++; + if (this._col > 39) { + this._col = 0; + this._row++; + } + } + if (this._row > 23) { + this._row = 23; + this._buffer.shift(); + this._buffer.push([]); + for (col = 0; col < 40; col++) { + this._buffer[this._row][col] = 0x20; + } + } + this._buffer[this._row][this._col] = 0x00; + this.refresh(); + } + writeAt(row: byte, col: byte, val: byte): void { + this._buffer[row][col] = val; + var data = this._page.data, + fore, + back, + color; + var off = (col * 14 + row * 560 * 8 * 2) * 4; + + fore = this._greenMode ? this._green : this._white; + back = this._black; + var char = 0; + + if (!val) { + if (this._blinking) { + fore = this._black; + } + } else { + char = val & 0x1f; + char |= val & 0x40 ? 0 : 0x20; + } + + for (var jdx = 0; jdx < 8; jdx++) { + var b = charset[char * 8 + jdx]; + for (var idx = 0; idx < 7; idx += 1) { + b <<= 1; + color = b & 0x80 ? fore : back; + var c0 = color[0], + c1 = color[1], + c2 = color[2]; + data[off + 0] = data[off + 4] = c0; + data[off + 1] = data[off + 5] = c1; + data[off + 2] = data[off + 6] = c2; + if (!this._scanlines) { + data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0; + data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1; + data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2; + } else { + data[off + 560 * 4] = data[off + 560 * 4 + 4] = c0 >> 1; + data[off + 560 * 4 + 1] = data[off + 560 * 4 + 5] = c1 >> 1; + data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2 >> 1; + } + off += 8; + } + off += 546 * 4 + 560 * 4; + } + } + _blink() { + for (var row = 0; row < 24; row++) { + for (var col = 0; col < 40; col++) { + var val = this._buffer[row][col]; + if (!val) { + this.writeAt(row, col, val); + } + } + } + this._dirty = true; + } + refresh() { + for (var row = 0; row < 24; row++) { + for (var col = 0; col < 40; col++) { + this.writeAt(row, col, this._buffer[row][col]); + } + } + this._dirty = true; + } + green(on: boolean) { + this._greenMode = on; + this.refresh(); + } + scanlines(on: boolean) { + this._scanlines = on; + this.refresh(); + } + blit() { + if (this._dirty) { + this._context.putImageData( + this._page, + 0, + 0, + 0, + 0, + 7 * 40 * 2, + 8 * 24 * 2 + ); + } + } + setContext(context: CanvasRenderingContext2D) { + this._context = context; + this._page = context.createImageData(560, 384); + for (var idx = 0; idx < 560 * 384 * 4; idx++) { + this._page.data[idx] = 0xff; + } + } + getText() { + function mapCharCode(charCode: byte) { + charCode &= 0x7f; + if (charCode < 0x20) { + charCode += 0x40; + } + if (charCode >= 0x60) { + charCode -= 0x40; + } + return charCode; + } + + var buffer = "", + line, + charCode; + var row, col; + for (row = 0; row < 24; row++) { + line = ""; + for (col = 0; col < 40; col++) { + charCode = mapCharCode(this._buffer[row][col]); + line += String.fromCharCode(charCode); + } + line = line.trimRight(); + buffer += line + "\n"; + } + return buffer; + } + clear() { + for (var row = 0; row < 24; row++) { + for (var col = 0; col < 40; col++) { + this._buffer[row][col] = 0x20; + } + } + this._col = 0; + this._row = 0; + this.refresh(); + } + + transcript = ""; +}