mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-01-08 18:30:05 +00:00
200 lines
7.1 KiB
JavaScript
200 lines
7.1 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.VCSBitmap48Decoder = exports.VCSVersatilePlayfieldDecoder = exports.VCSPlayfieldDecoder = exports.VCSBitmapDecoder = exports.VCSSpriteDecoder = void 0;
|
|
exports.newDecoder = newDecoder;
|
|
const ecs_1 = require("./ecs");
|
|
class LineDecoder {
|
|
constructor(text) {
|
|
this.curline = 0; // for debugging, zero-indexed
|
|
// split the text into lines and into tokens
|
|
this.lines = text.split('\n').map(s => s.trim()).filter(s => !!s).map(s => s.split(/\s+/));
|
|
}
|
|
decodeBits(s, n, msbfirst) {
|
|
if (s.length != n)
|
|
throw new ecs_1.ECSError(`Expected ${n} characters`);
|
|
let b = 0;
|
|
for (let i = 0; i < n; i++) {
|
|
let bit;
|
|
let ch = s.charAt(i);
|
|
if (ch == 'x' || ch == 'X' || ch == '1')
|
|
bit = 1;
|
|
else if (ch == '.' || ch == '0')
|
|
bit = 0;
|
|
else
|
|
throw new ecs_1.ECSError('need x or . (or 0 or 1)');
|
|
if (bit) {
|
|
if (msbfirst)
|
|
b |= 1 << (n - 1 - i);
|
|
else
|
|
b |= 1 << i;
|
|
}
|
|
}
|
|
return b;
|
|
}
|
|
assertTokens(toks, count) {
|
|
if (toks.length != count)
|
|
throw new ecs_1.ECSError(`Expected ${count} tokens on line.`);
|
|
}
|
|
hex(s) {
|
|
let v = parseInt(s, 16);
|
|
if (isNaN(v))
|
|
throw new ecs_1.ECSError(`Invalid hex value: ${s}`);
|
|
return v;
|
|
}
|
|
getErrorLocation($loc) {
|
|
// TODO: blank lines mess this up
|
|
$loc.line += this.curline + 1;
|
|
return $loc;
|
|
}
|
|
}
|
|
class VCSSpriteDecoder extends LineDecoder {
|
|
parse() {
|
|
let height = this.lines.length;
|
|
let bitmapdata = new Uint8Array(height);
|
|
let colormapdata = new Uint8Array(height);
|
|
for (let i = 0; i < height; i++) {
|
|
this.curline = height - 1 - i;
|
|
let toks = this.lines[this.curline];
|
|
this.assertTokens(toks, 2);
|
|
bitmapdata[i] = this.decodeBits(toks[0], 8, true);
|
|
colormapdata[i] = this.hex(toks[1]);
|
|
}
|
|
return {
|
|
properties: {
|
|
bitmapdata, colormapdata, height: height - 1
|
|
}
|
|
};
|
|
}
|
|
}
|
|
exports.VCSSpriteDecoder = VCSSpriteDecoder;
|
|
class VCSBitmapDecoder extends LineDecoder {
|
|
parse() {
|
|
let height = this.lines.length;
|
|
let bitmapdata = new Uint8Array(height);
|
|
for (let i = 0; i < height; i++) {
|
|
this.curline = height - 1 - i;
|
|
let toks = this.lines[this.curline];
|
|
this.assertTokens(toks, 1);
|
|
bitmapdata[i] = this.decodeBits(toks[0], 8, true);
|
|
}
|
|
return {
|
|
properties: {
|
|
bitmapdata, height: height - 1
|
|
}
|
|
};
|
|
}
|
|
}
|
|
exports.VCSBitmapDecoder = VCSBitmapDecoder;
|
|
class VCSPlayfieldDecoder extends LineDecoder {
|
|
parse() {
|
|
let height = this.lines.length;
|
|
let pf = new Uint32Array(height);
|
|
for (let i = 0; i < height; i++) {
|
|
this.curline = height - 1 - i;
|
|
let toks = this.lines[this.curline];
|
|
this.assertTokens(toks, 1);
|
|
let pf0 = this.decodeBits(toks[0].substring(0, 4), 4, false) << 4;
|
|
let pf1 = this.decodeBits(toks[0].substring(4, 12), 8, true);
|
|
let pf2 = this.decodeBits(toks[0].substring(12, 20), 8, false);
|
|
pf[i] = (pf0 << 0) | (pf1 << 8) | (pf2 << 16);
|
|
}
|
|
return {
|
|
properties: {
|
|
pf
|
|
}
|
|
};
|
|
}
|
|
}
|
|
exports.VCSPlayfieldDecoder = VCSPlayfieldDecoder;
|
|
class VCSVersatilePlayfieldDecoder extends LineDecoder {
|
|
parse() {
|
|
let height = this.lines.length;
|
|
let data = new Uint8Array(height * 2);
|
|
data.fill(0x3f);
|
|
// pf0 pf1 pf2 colupf colubk ctrlpf trash
|
|
const regs = [0x0d, 0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x3f];
|
|
let prev = [0, 0, 0, 0, 0, 0, 0];
|
|
let cur = [0, 0, 0, 0, 0, 0, 0];
|
|
for (let i = 0; i < height; i++) {
|
|
let dataofs = height * 2 - i * 2;
|
|
this.curline = i;
|
|
let toks = this.lines[this.curline];
|
|
if (toks.length == 2) {
|
|
data[dataofs - 1] = this.hex(toks[0]);
|
|
data[dataofs - 2] = this.hex(toks[1]);
|
|
continue;
|
|
}
|
|
this.assertTokens(toks, 4);
|
|
cur[0] = this.decodeBits(toks[0].substring(0, 4), 4, false) << 4;
|
|
cur[1] = this.decodeBits(toks[0].substring(4, 12), 8, true);
|
|
cur[2] = this.decodeBits(toks[0].substring(12, 20), 8, false);
|
|
if (toks[1] != '..')
|
|
cur[3] = this.hex(toks[1]);
|
|
if (toks[2] != '..')
|
|
cur[4] = this.hex(toks[2]);
|
|
if (toks[3] != '..')
|
|
cur[5] = this.hex(toks[3]);
|
|
let changed = [];
|
|
for (let j = 0; j < cur.length; j++) {
|
|
if (cur[j] != prev[j])
|
|
changed.push(j);
|
|
}
|
|
if (changed.length > 1) {
|
|
console.log(changed, cur, prev);
|
|
throw new ecs_1.ECSError(`More than one register change in line ${i + 1}: [${changed}]`);
|
|
}
|
|
let chgidx = changed.length ? changed[0] : regs.length - 1;
|
|
data[dataofs - 1] = regs[chgidx];
|
|
data[dataofs - 2] = cur[chgidx];
|
|
prev[chgidx] = cur[chgidx];
|
|
}
|
|
return {
|
|
properties: {
|
|
data
|
|
}
|
|
};
|
|
}
|
|
}
|
|
exports.VCSVersatilePlayfieldDecoder = VCSVersatilePlayfieldDecoder;
|
|
class VCSBitmap48Decoder extends LineDecoder {
|
|
parse() {
|
|
let height = this.lines.length;
|
|
let bitmap0 = new Uint8Array(height);
|
|
let bitmap1 = new Uint8Array(height);
|
|
let bitmap2 = new Uint8Array(height);
|
|
let bitmap3 = new Uint8Array(height);
|
|
let bitmap4 = new Uint8Array(height);
|
|
let bitmap5 = new Uint8Array(height);
|
|
for (let i = 0; i < height; i++) {
|
|
this.curline = height - 1 - i;
|
|
let toks = this.lines[this.curline];
|
|
this.assertTokens(toks, 1);
|
|
bitmap0[i] = this.decodeBits(toks[0].slice(0, 8), 8, true);
|
|
bitmap1[i] = this.decodeBits(toks[0].slice(8, 16), 8, true);
|
|
bitmap2[i] = this.decodeBits(toks[0].slice(16, 24), 8, true);
|
|
bitmap3[i] = this.decodeBits(toks[0].slice(24, 32), 8, true);
|
|
bitmap4[i] = this.decodeBits(toks[0].slice(32, 40), 8, true);
|
|
bitmap5[i] = this.decodeBits(toks[0].slice(40, 48), 8, true);
|
|
}
|
|
return {
|
|
properties: {
|
|
bitmap0, bitmap1, bitmap2, bitmap3, bitmap4, bitmap5,
|
|
height: height - 1
|
|
}
|
|
};
|
|
}
|
|
}
|
|
exports.VCSBitmap48Decoder = VCSBitmap48Decoder;
|
|
function newDecoder(name, text) {
|
|
let cons = DECODERS[name];
|
|
if (cons)
|
|
return new cons(text);
|
|
}
|
|
const DECODERS = {
|
|
'vcs_sprite': VCSSpriteDecoder,
|
|
'vcs_bitmap': VCSBitmapDecoder,
|
|
'vcs_playfield': VCSPlayfieldDecoder,
|
|
'vcs_versatile': VCSVersatilePlayfieldDecoder,
|
|
'vcs_bitmap48': VCSBitmap48Decoder,
|
|
};
|
|
//# sourceMappingURL=decoder.js.map
|