84 lines
2.4 KiB
JavaScript
84 lines
2.4 KiB
JavaScript
export const VSYNC = 0x80;
|
|
export const HSYNC = 0x40;
|
|
|
|
/** Vga */
|
|
export class Vga {
|
|
/** Create a new Vga
|
|
* @param {HTMLCanvasElement} canvas
|
|
* @param {Gigatron} cpu
|
|
* @param {Object} options
|
|
*/
|
|
constructor(canvas, cpu, options) {
|
|
this.canvas = canvas;
|
|
this.canvas.width = options.horizontal.visible;
|
|
this.canvas.height = options.vertical.visible;
|
|
this.ctx = canvas.getContext('2d', {
|
|
alpha: false,
|
|
});
|
|
this.imageData = this.ctx.getImageData(
|
|
0, 0,
|
|
canvas.width, canvas.height);
|
|
this.pixels = this.imageData.data;
|
|
this.cpu = cpu;
|
|
this.row = 0;
|
|
this.minRow = options.vertical.backPorch + options.vertical.pulse;
|
|
this.maxRow = this.minRow + options.vertical.visible;
|
|
this.col = 0;
|
|
this.minCol = options.horizontal.backPorch + options.horizontal.pulse;
|
|
this.maxCol = this.minCol + options.horizontal.visible;
|
|
this.pixel = 0;
|
|
this.out = 0;
|
|
// turn all pixels black with full alpha
|
|
for (let i = 0; i < this.pixels.length; i++) {
|
|
this.pixels[i] = (i % 4) == 3 ? 255 : 0;
|
|
}
|
|
this.render();
|
|
}
|
|
|
|
/** draw the pixels into the canvas */
|
|
render() {
|
|
this.ctx.putImageData(this.imageData, 0, 0);
|
|
}
|
|
|
|
/** advance simulation by one tick */
|
|
tick() {
|
|
let out = this.cpu.out;
|
|
let falling = this.out & ~out;
|
|
|
|
if (falling & VSYNC) {
|
|
this.row = -1; // After 4 more CPU cycles HSYNC increments row to 0
|
|
this.pixel = 0;
|
|
this.render();
|
|
}
|
|
|
|
if (falling & HSYNC) {
|
|
this.col = 0;
|
|
this.row++;
|
|
}
|
|
|
|
// Chrome optimizer put this before the falling calculation
|
|
// if it follows immediately after it, so it got moved down here
|
|
this.out = out;
|
|
|
|
if ((this.row >= this.minRow && this.row < this.maxRow) &&
|
|
(this.col >= this.minCol && this.col < this.maxCol)) {
|
|
let pixels = this.pixels;
|
|
let pixel = this.pixel;
|
|
let r = (out ) & 3;
|
|
let g = (out >> 2) & 3;
|
|
let b = (out >> 4) & 3;
|
|
|
|
for (let i = 0; i < 4; i++) {
|
|
pixels[pixel++] = 85 * r;
|
|
pixels[pixel++] = 85 * g;
|
|
pixels[pixel++] = 85 * b;
|
|
pixel++;
|
|
}
|
|
|
|
this.pixel = pixel;
|
|
}
|
|
|
|
this.col += 4;
|
|
}
|
|
}
|