export className Screen { constructor(scale, canvas) { this.display = new Array(32 * 64).fill(0); this.scale = scale; this.canvas = canvas; this.ctx = this.canvas.getContext('2d'); this.colors = { fill: '#000', bg: 'white', }; this.canvas.width = COLS * this.scale; this.canvas.height = ROWS * this.scale; } }
export className Screen { constructor(scale, canvas) { this.display = new Array(32 * 64).fill(0); this.scale = scale; this.canvas = canvas; this.ctx = this.canvas.getContext('2d'); this.colors = { fill: '#000', bg: 'white', }; this.canvas.width = COLS * this.scale; this.canvas.height = ROWS * this.scale; } }
export className Screen { constructor(scale, canvas) { this.display = new Array(32 * 64).fill(0); this.scale = scale; this.canvas = canvas; this.ctx = this.canvas.getContext('2d'); this.colors = { fill: '#000', bg: 'white', }; this.canvas.width = COLS * this.scale; this.canvas.height = ROWS * this.scale; } }
export className Screen { constructor(scale, canvas) { this.display = new Array(32 * 64).fill(0); this.scale = scale; this.canvas = canvas; this.ctx = this.canvas.getContext('2d'); this.colors = { fill: '#000', bg: 'white', }; this.canvas.width = COLS * this.scale; this.canvas.height = ROWS * this.scale; } }
export className Screen { constructor(scale, canvas) { this.display = new Array(32 * 64).fill(0); this.scale = scale; this.canvas = canvas; this.ctx = this.canvas.getContext('2d'); this.colors = { fill: '#000', bg: 'white', }; this.canvas.width = COLS * this.scale; this.canvas.height = ROWS * this.scale; } }
[
162, 204, 106, 6, 97, 3, 107, 8, 96, 0, 208, 17, 112, 8, 123,
255, 59, 0, 18, 10, 113, 2, 122, 255, 58, 0, 18, 6, 102, 0, 103,
20, 162, 205, 96, 32, 97, 30, 208, 17, 99, 29, 98, 63, 130, 2,
119, 255, 71, 0, 18, 170, 255, 10, 162, 203, 210, 49, 101, 255,
196, 1, 52, 1, 100, 255, 162, 205, 108, 0, 110, 4, 238, 161,
108, 254, 110, 6, 238, 161, 108, 2, 208, 17, 128, 196, 208, 17,
79, 1, 18, 152, 66, 0, 100, 1, 66, 63, 100, 255, 67, 0, 18, 206,
67, 31, 18, 164, 162, 203, 210, 49, 130, 68, 131, 84, 210, 49,
63, 1, 18, 66, 67, 30, 18, 152, 106, 2, 250, 24, 118, 1, 162,
202, 18, 136, 210, 49, 196, 1, 52, 1, 100, 255, 197, 1, 53, 1,
101, 1, 18, 66, 106, 3, 250, 24, 162, 203, 210, 49, 115, 255,
18, 54, 162, 203, 210, 49, 18, 40, 162, 205, 208, 17, 162, 240,
246, 51, 242, 101, 99, 24, 100, 27, 240, 41, 211, 69, 115, 5,
241, 41, 211, 69, 115, 5, 242, 41, 211, 69, 18, 200, 240, 128,
255, 255, 162, 222, 99, 21, 98, 16, 211, 37, 162, 227, 99, 29,
211, 37, 18, 170, 238, 138, 206, 140, 138, 238, 136, 204, 136
];
Decimal: 0-9
Hexadecimal: 0-F
#FFFFFF
FF FF FF
F F
(15*161) +(15*160)
(15 * 16) + (15 * 1)
255
255 255 255
& -> 0x12 & 0x10 = 0x10
| -> 0x12 | 0x10 = 0x12
^ -> 0x12 ^ 0x10 = 0x2
switch (opcode & 0xf000) { // 0x42f3 & 0xf000 -> 0x4000 case 0x0000: switch (opcode) { case 0x00e0: this.renderer.clear(); break; case 0x00ee: this.pc = this.stack.pop()!; break; } break; }
switch (opcode & 0xf000) { // 0x42f3 & 0xf000 -> 0x4000 case 0x0000: switch (opcode) { case 0x00e0: this.renderer.clear(); break; case 0x00ee: this.pc = this.stack.pop()!; break; } break; }
switch (opcode & 0xf000) { // 0x42f3 & 0xf000 -> 0x4000 case 0x0000: switch (opcode) { case 0x00e0: this.renderer.clear(); break; case 0x00ee: this.pc = this.stack.pop()!; break; } break; }
switch (opcode & 0xf000) {
case 0x0000:
switch (opcode) {
case 0x00e0:
this.renderer.clear();
break;
case 0x00ee:
this.pc = this.stack.pop()!;
break;
}
break;
case 0x1000:
this.pc = opcode & 0xfff;
break;
case 0x2000:
this.stack.push(this.pc);
this.pc = opcode & 0xfff;
break;
case 0x3000:
if (this.registers8[x] === (opcode & 0xff)) {
this.pc += 2;
}
break;
case 0x4000:
if (this.registers8[x] !== (opcode & 0xff)) {
this.pc += 2;
}
break;
case 0x5000:
if (this.registers8[x] === this.registers8[y]) {
this.pc += 2;
}
break;
case 0x6000:
this.registers8[x] = opcode & 0xff;
break;
case 0x7000:
this.registers8[x] += opcode & 0xff;
break;
case 0x8000:
switch (opcode & 0xf) {
case 0x0:
this.registers8[x] = this.registers8[y];
break;
case 0x1:
this.registers8[x] |= this.registers8[y];
break;
case 0x2:
this.registers8[x] &= this.registers8[y];
break;
case 0x3:
this.registers8[x] ^= this.registers8[y];
break;
case 0x4: {
const sum = (this.registers8[x] += this.registers8[y]);
this.registers8[0xf] = 0;
if (sum > 0xff) {
this.registers8[0xf] = 1;
}
this.registers8[x] = sum;
break;
}
case 0x5:
this.registers8[0xf] = 0;
if (this.registers8[x] > this.registers8[y]) {
this.registers8[0xf] = 1;
}
this.registers8[x] -= this.registers8[y];
break;
case 0x6:
this.registers8[0xf] = this.registers8[x] & 0x1;
this.registers8[x] >>= 1;
break;
case 0x7:
this.registers8[0xf] = 0;
if (this.registers8[y] > this.registers8[x]) {
this.registers8[0xf] = 1;
}
this.registers8[x] = this.registers8[y] - this.registers8[x];
break;
case 0xe:
this.registers8[0xf] = this.registers8[x] & 0x80;
this.registers8[x] <<= 1;
break;
}
break;
case 0x9000:
if (this.registers8[x] !== this.registers8[y]) {
this.pc += 2;
}
break;
case 0xa000:
this.i = opcode & 0xfff;
break;
case 0xb000:
this.pc = (opcode & 0xfff) + this.registers8[0];
break;
case 0xc000: {
const rand = Math.floor(Math.random() * 0xff);
this.registers8[x] = rand & (opcode & 0xff);
break;
}
case 0xd000: {
const width = 8;
const height = opcode & 0xf;
this.registers8[0xf] = 0;
for (let row = 0; row < height; row++) {
let sprite = this.memory[this.i + row];
for (let col = 0; col < width; col++) {
// If the bit (sprite) is not 0, render/erase the pixel
if ((sprite & 0x80) > 0) {
// If setPixel returns 1, which means a pixel was erased, set VF to 1
if (
this.renderer.setPixel(
this.registers8[x] + col,
this.registers8[y] + row
)
) {
this.registers8[0xf] = 1;
}
}
// Shift the sprite left 1. This will move the next next col/bit of the sprite into the first position.
// Ex. 10010000 << 1 will become 0010000
sprite <<= 1;
}
}
break;
}
case 0xe000:
switch (opcode & 0xff) {
case 0x9e:
if (this.keyboard.isKeyPressed(this.registers8[x])) {
this.pc += 2;
}
break;
case 0xa1:
if (!this.keyboard.isKeyPressed(this.registers8[x])) {
this.pc += 2;
}
break;
}
break;
case 0xf000:
switch (opcode & 0xff) {
case 0x07:
this.registers8[x] = this.delayTimer;
break;
case 0x0a:
this.paused = true;
this.keyboard.onNextKeyPress = key => {
this.registers8[x] = key;
this.paused = false;
};
break;
case 0x15:
this.delayTimer = this.registers8[x];
break;
case 0x18:
this.soundTimer = this.registers8[x];
break;
case 0x1e:
this.i += this.registers8[x];
break;
case 0x29:
this.i = this.registers8[x] * 5;
break;
case 0x33:
// Get the hundreds digit and place it in I.
this.memory[this.i] = Math.round(this.registers8[x] / 100);
// Get tens digit and place it in I+1. Gets a value between 0 and 99, then divides by 10 to give us a value
// between 0 and 9.
this.memory[this.i + 1] = Math.round(
(this.registers8[x] % 100) / 10
);
// Get the value of the ones (last) digit and place it in I+2. 0 through 9.
this.memory[this.i + 2] = Math.round(this.registers8[x] % 10);
break;
case 0x55:
for (let registerIndex = 0; registerIndex <= x; registerIndex++) {
this.memory[this.i + registerIndex] = this.registers8[
registerIndex
];
}
break;
case 0x65:
for (let registerIndex = 0; registerIndex <= x; registerIndex++) {
this.registers8[registerIndex] = this.memory[
this.i + registerIndex
];
}
break;
}
break;
default:
throw new Error('Unknown opcode ' + opcode);
}
npm i @saravieira/chippy