All instructions done
This commit is contained in:
parent
821c327ed3
commit
ee3136bb5f
@ -3,16 +3,14 @@ import Keyboard from './keyboard'
|
|||||||
import RNG from './RNG'
|
import RNG from './RNG'
|
||||||
|
|
||||||
class Chip8Emulator {
|
class Chip8Emulator {
|
||||||
|
|
||||||
cpu: CPU;
|
cpu: CPU;
|
||||||
keyboard: Keyboard;
|
keyboard: Keyboard;
|
||||||
|
|
||||||
rom: Uint8Array;
|
rom: Uint8Array;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
this.cpu = new CPU();
|
|
||||||
this.keyboard = new Keyboard();
|
this.keyboard = new Keyboard();
|
||||||
|
this.cpu = new CPU(this.keyboard);
|
||||||
|
|
||||||
this.rom = new Uint8Array();
|
this.rom = new Uint8Array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
130
src/cpu.ts
130
src/cpu.ts
@ -1,4 +1,5 @@
|
|||||||
import RNG from './RNG'
|
import RNG from './RNG'
|
||||||
|
import Keyboard from './keyboard';
|
||||||
|
|
||||||
const SCREEN_WIDTH = 64;
|
const SCREEN_WIDTH = 64;
|
||||||
const SCREEN_HEIGHT = 32;
|
const SCREEN_HEIGHT = 32;
|
||||||
@ -22,9 +23,12 @@ class CPU {
|
|||||||
memory: Uint8Array;
|
memory: Uint8Array;
|
||||||
displayMemory: Uint8Array;
|
displayMemory: Uint8Array;
|
||||||
|
|
||||||
rng: RNG;
|
keyboard: Keyboard;
|
||||||
|
|
||||||
constructor() {
|
rng: RNG;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(keyboard: Keyboard) {
|
||||||
this.memory = new Uint8Array(MEMORY_SIZE);
|
this.memory = new Uint8Array(MEMORY_SIZE);
|
||||||
this.displayMemory = new Uint8Array(SCREEN_WIDTH*SCREEN_HEIGHT);
|
this.displayMemory = new Uint8Array(SCREEN_WIDTH*SCREEN_HEIGHT);
|
||||||
this.pc = 0x200;
|
this.pc = 0x200;
|
||||||
@ -34,6 +38,7 @@ class CPU {
|
|||||||
this.delayTimer = 0;
|
this.delayTimer = 0;
|
||||||
this.soundTimer = 0;
|
this.soundTimer = 0;
|
||||||
this.regs = new Uint8Array(REGISTERS);
|
this.regs = new Uint8Array(REGISTERS);
|
||||||
|
this.keyboard = keyboard;
|
||||||
|
|
||||||
this.rng = new RNG(0);
|
this.rng = new RNG(0);
|
||||||
|
|
||||||
@ -268,29 +273,128 @@ class CPU {
|
|||||||
case 0xD: {
|
case 0xD: {
|
||||||
// DXYN
|
// DXYN
|
||||||
// draw(Vx, Vy, N)
|
// draw(Vx, Vy, N)
|
||||||
this.regs[0xF] = 0;
|
this.regs[0xF] = 0; // Reset register VF
|
||||||
|
|
||||||
let regX = this.regs[nib2];
|
let regX = this.regs[nib2];
|
||||||
let regY = this.regs[nib3];
|
let regY = this.regs[nib3];
|
||||||
|
|
||||||
let y = 0;
|
for(let y = 0; y < nib4; y++) {
|
||||||
while(y < nib4) {
|
|
||||||
// A sprite is always 8 bits horizontal
|
// A sprite is always 8 bits horizontal
|
||||||
let pixel = this.memory[this.indexReg + y];
|
let pixel = this.memory[this.indexReg + y]; // Fetch pixel from memory starting at I reg
|
||||||
let x = 0;
|
|
||||||
while(x < 8) {
|
for(let x = 0; x < 8; x++) {
|
||||||
const msb = 0x80;
|
const MSB = 0x80; // 0b10000000
|
||||||
|
|
||||||
|
if((pixel & (MSB >> x)) != 0) {
|
||||||
x++;
|
let mem = x + regX + ((y + regY) * SCREEN_WIDTH);
|
||||||
|
if(this.displayMemory[mem] == 1) {
|
||||||
|
this.regs[0xF] = 1;
|
||||||
|
}
|
||||||
|
this.displayMemory[mem] ^= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.incrementPC();
|
this.incrementPC();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0xE: {
|
||||||
|
if(secondOpcode == 0x9E) {
|
||||||
|
// EX9E
|
||||||
|
// if (key() == Vx)
|
||||||
|
// Skips the next instruction if the key stored at VX is pressed
|
||||||
|
if(this.keyboard.keys[this.regs[nib2]] == 1) {
|
||||||
|
this.incrementPC();
|
||||||
|
}
|
||||||
|
}else if(secondOpcode == 0xA1) {
|
||||||
|
// EXA1
|
||||||
|
// if (key() != Vx)
|
||||||
|
// Skips the next instruction if the key stored at VX is NOT pressed
|
||||||
|
if(this.keyboard.keys[this.regs[nib2]] != 1) {
|
||||||
|
this.incrementPC();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.incrementPC();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xF: {
|
||||||
|
if(secondOpcode == 0x07) {
|
||||||
|
// FX07
|
||||||
|
// Vx = delayTimer
|
||||||
|
this.regs[nib2] = this.delayTimer;
|
||||||
|
this.incrementPC();
|
||||||
|
}else if(secondOpcode == 0x0A) {
|
||||||
|
// FX0A
|
||||||
|
// A key pressed is awaited and then stored at VX.
|
||||||
|
// [BLOCKING OPERATION], all instructions are halted until next key event
|
||||||
|
// Vx = get_key()
|
||||||
|
let keyPressed = false;
|
||||||
|
|
||||||
|
for(let i = 0; i < this.keyboard.keys.length; i++) {
|
||||||
|
if(this.keyboard.keys[i] != 0) {
|
||||||
|
keyPressed = true;
|
||||||
|
this.regs[nib2] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!keyPressed)
|
||||||
|
return; // NOT INCREMENT PC SO WE ARE STUCK IN THIS WAITING
|
||||||
|
|
||||||
|
this.incrementPC();
|
||||||
|
}else if(secondOpcode == 0x15) {
|
||||||
|
// FX15
|
||||||
|
// delayTimer = Vx
|
||||||
|
this.delayTimer = this.regs[nib2];
|
||||||
|
this.incrementPC();
|
||||||
|
}else if(secondOpcode == 0x18) {
|
||||||
|
// FX18
|
||||||
|
// soundTimer = Vx
|
||||||
|
this.soundTimer = this.regs[nib2];
|
||||||
|
this.incrementPC();
|
||||||
|
}else if(secondOpcode == 0x1E) {
|
||||||
|
// FX1E
|
||||||
|
// I += Vx
|
||||||
|
// Adds VX to I. VF is not affected
|
||||||
|
this.indexReg += this.regs[nib2];
|
||||||
|
this.incrementPC();
|
||||||
|
}else if(secondOpcode == 0x29) {
|
||||||
|
// FX29
|
||||||
|
// I = sprite_addr[Vx]
|
||||||
|
// Sets I to the location of the sprite for the character in VX
|
||||||
|
this.indexReg = this.regs[nib2] * 0x5; // ??
|
||||||
|
this.incrementPC();
|
||||||
|
}else if(secondOpcode == 0x33) {
|
||||||
|
// FX33
|
||||||
|
// set_BCD(Vx)
|
||||||
|
// *(I+0) = BCD(3);
|
||||||
|
// *(I+1) = BCD(2);
|
||||||
|
// *(I+2) = BCD(1);
|
||||||
|
// Stores the binary-coded decimal representation of Vx, with the hundreds digit memory at location in I,
|
||||||
|
//
|
||||||
|
this.memory[this.indexReg] = this.regs[nib2] / 100;
|
||||||
|
this.memory[this.indexReg + 1] = (this.regs[nib2] / 10) % 10;
|
||||||
|
this.memory[this.indexReg + 2] = this.regs[nib2] % 10;
|
||||||
|
this.incrementPC();
|
||||||
|
}else if(secondOpcode == 0x55) {
|
||||||
|
// FX55
|
||||||
|
// reg_dump(Vx, &I)
|
||||||
|
// Stores from V0 to VX in memory starting at address I.
|
||||||
|
for(let i = 0; i < nib2; i++) {
|
||||||
|
this.memory[this.indexReg + i] = this.regs[i];
|
||||||
|
}
|
||||||
|
this.incrementPC();
|
||||||
|
}else if(secondOpcode == 0x65) {
|
||||||
|
// FX65
|
||||||
|
// reg_load(Vx, &I)
|
||||||
|
// Fills fomr V0 to VX with values from memory staring at address I.
|
||||||
|
for(let i = 0; i < nib2; i++) {
|
||||||
|
this.regs[i] = this.memory[this.indexReg + i];
|
||||||
|
}
|
||||||
|
this.incrementPC();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user