All instructions done
This commit is contained in:
parent
821c327ed3
commit
ee3136bb5f
@ -3,16 +3,14 @@ import Keyboard from './keyboard'
|
||||
import RNG from './RNG'
|
||||
|
||||
class Chip8Emulator {
|
||||
|
||||
cpu: CPU;
|
||||
keyboard: Keyboard;
|
||||
|
||||
rom: Uint8Array;
|
||||
|
||||
constructor() {
|
||||
|
||||
this.cpu = new CPU();
|
||||
this.keyboard = new Keyboard();
|
||||
this.cpu = new CPU(this.keyboard);
|
||||
|
||||
this.rom = new Uint8Array();
|
||||
}
|
||||
|
||||
|
126
src/cpu.ts
126
src/cpu.ts
@ -1,4 +1,5 @@
|
||||
import RNG from './RNG'
|
||||
import Keyboard from './keyboard';
|
||||
|
||||
const SCREEN_WIDTH = 64;
|
||||
const SCREEN_HEIGHT = 32;
|
||||
@ -22,9 +23,12 @@ class CPU {
|
||||
memory: Uint8Array;
|
||||
displayMemory: Uint8Array;
|
||||
|
||||
keyboard: Keyboard;
|
||||
|
||||
rng: RNG;
|
||||
|
||||
constructor() {
|
||||
|
||||
constructor(keyboard: Keyboard) {
|
||||
this.memory = new Uint8Array(MEMORY_SIZE);
|
||||
this.displayMemory = new Uint8Array(SCREEN_WIDTH*SCREEN_HEIGHT);
|
||||
this.pc = 0x200;
|
||||
@ -34,6 +38,7 @@ class CPU {
|
||||
this.delayTimer = 0;
|
||||
this.soundTimer = 0;
|
||||
this.regs = new Uint8Array(REGISTERS);
|
||||
this.keyboard = keyboard;
|
||||
|
||||
this.rng = new RNG(0);
|
||||
|
||||
@ -268,29 +273,128 @@ class CPU {
|
||||
case 0xD: {
|
||||
// DXYN
|
||||
// draw(Vx, Vy, N)
|
||||
this.regs[0xF] = 0;
|
||||
this.regs[0xF] = 0; // Reset register VF
|
||||
|
||||
let regX = this.regs[nib2];
|
||||
let regY = this.regs[nib3];
|
||||
|
||||
let y = 0;
|
||||
while(y < nib4) {
|
||||
for(let y = 0; y < nib4; y++) {
|
||||
// A sprite is always 8 bits horizontal
|
||||
let pixel = this.memory[this.indexReg + y];
|
||||
let x = 0;
|
||||
while(x < 8) {
|
||||
const msb = 0x80;
|
||||
let pixel = this.memory[this.indexReg + y]; // Fetch pixel from memory starting at I reg
|
||||
|
||||
for(let x = 0; x < 8; x++) {
|
||||
const MSB = 0x80; // 0b10000000
|
||||
|
||||
x++;
|
||||
if((pixel & (MSB >> x)) != 0) {
|
||||
let mem = x + regX + ((y + regY) * SCREEN_WIDTH);
|
||||
if(this.displayMemory[mem] == 1) {
|
||||
this.regs[0xF] = 1;
|
||||
}
|
||||
this.displayMemory[mem] ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
this.incrementPC();
|
||||
}
|
||||
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