From a56d78787828fc9fce0d08a9469e4f2a50782eba Mon Sep 17 00:00:00 2001 From: MichaelValwin Date: Wed, 4 Sep 2024 21:38:54 +0200 Subject: [PATCH] Fix some instructions --- index.html | 43 ++++++++++------- src/chip8Emulator.ts | 25 ++++++---- src/cpu.ts | 109 ++++++++++++++++++++++++++++++------------- 3 files changed, 117 insertions(+), 60 deletions(-) diff --git a/index.html b/index.html index c6924f3..6a8e543 100644 --- a/index.html +++ b/index.html @@ -23,33 +23,40 @@

Chip 8 emulator

- + \ No newline at end of file diff --git a/src/chip8Emulator.ts b/src/chip8Emulator.ts index 29dedc1..b77fba5 100644 --- a/src/chip8Emulator.ts +++ b/src/chip8Emulator.ts @@ -7,27 +7,32 @@ class Chip8Emulator { keyboard: Keyboard; rom: Uint8Array; + romLoaded: boolean; + constructor() { this.keyboard = new Keyboard(); this.cpu = new CPU(this.keyboard); this.rom = new Uint8Array(); + this.romLoaded = false; } loadRom(rom: Uint8Array) { this.rom = rom; + this.cpu.loadRom(this.rom); + this.romLoaded = true; + } + + isRomLoaded() { + return this.romLoaded; } emulateCycle() { - // Fetch opcode - // Decode opcode - // Execute opcode - - // Update timers + this.cpu.cycle(); } - drawGraphics() { - + getCPUStatus() : string { + return this.cpu.getCPUStatus(); } drawToCanvas(canvas: HTMLCanvasElement, size: number) { @@ -43,11 +48,11 @@ class Chip8Emulator { for(let i = 0; i < this.cpu.displayMemory.length; i++) { let isOn: number = this.cpu.displayMemory[i]; if(isOn === 1) { - let y = Math.floor(i/width); - let x = i - (y*width); + let y = Math.floor(i/64); + let x = i - (y*64); ctx.fillStyle = "WHITE"; - ctx.fillRect(x, y, 1, 1); + ctx.fillRect(x*size, y*size, size, size); } } } diff --git a/src/cpu.ts b/src/cpu.ts index a887f8c..3b85f97 100644 --- a/src/cpu.ts +++ b/src/cpu.ts @@ -18,7 +18,7 @@ class CPU { soundTimer: number; // 8b stackPointer: number; // 16b - stack: Array; + stack: Uint16Array; memory: Uint8Array; displayMemory: Uint8Array; @@ -34,7 +34,7 @@ class CPU { this.pc = 0x200; this.indexReg = 0; this.stackPointer = 0; - this.stack = new Array(STACK_SIZE); + this.stack = new Uint16Array(STACK_SIZE); this.delayTimer = 0; this.soundTimer = 0; this.regs = new Uint8Array(REGISTERS); @@ -99,11 +99,40 @@ class CPU { this.memory.set(characters, addressFont); } + public loadRom(rom: Uint8Array) { + // Loads a ROM into starting PC addres?? + console.log(rom); + for(let i = 0; i < rom.length; i++) { + this.memory[this.pc+i] = rom[i]; + } + this.memory.set(rom, this.pc); + } + + public getCPUStatus() : string{ + let status = ""; + status += "PC: " + this.pc + "\n"; + status += "I: " + this.indexReg.toString(16) + "\n"; + for(let i = 0; i < REGISTERS; i++) { + status += "V" + i + ": " + this.regs[i].toString(16).toUpperCase().padStart(2, '0') + "\n"; + } + status += "SP: " + this.stackPointer.toString(16) + "\n"; + for(let i = 0; i < this.stackPointer; i++) { + status += "ST" + i + ": " + this.stack[i] + "\n"; + } + status += "\n"; + let firstOpcode: number = this.memory[this.pc]; + let secondOpcode: number = this.memory[this.pc + 1]; + let opcode: number = firstOpcode << 8 | secondOpcode; + status += "OPCODE FOR PC: " + opcode.toString(16).toUpperCase().padStart(4, '0') + "\n"; + + return status; + } + private incrementPC() { this.pc += 2; } - private cycle() { + public cycle() { // Fetch opcode let firstOpcode: number = this.memory[this.pc]; let secondOpcode: number = this.memory[this.pc + 1]; @@ -111,38 +140,47 @@ class CPU { // Decode opcode let nib1 = firstOpcode >> 4; // X000 - let nib2 = firstOpcode & 0xF; // 0X00 + let nib2 = firstOpcode & 0x0F; // 0X00 let nib3 = secondOpcode >> 4; // 00X0 - let nib4 = secondOpcode & 0xF; // 000X + let nib4 = secondOpcode & 0x0F; // 000X switch(nib1) { case 0x0: if(opcode == 0x00E0) { + // 00E0 // Clear the screen this.clearDisplay(); + this.incrementPC(); }else if(opcode == 0x00EE) { + // 00EE // Returns from a subroutine this.stackPointer--; - this.pc = this.stack[this.pc]; + if(this.stackPointer < 0) { + throw new Error("Stack pointer cant go to -1"); + } + this.pc = this.stack[this.stackPointer]; } - this.incrementPC(); break; - case 0x1: + case 0x1: { + // 1NNN // goto NNN; - let threeNib = opcode & 0x0FFF; - this.pc = threeNib; + let address = opcode & 0x0FFF; + this.pc = address; + } break; - case 0x2: + case 0x2: { + // 2NNN // Calls subroutine at NNN - this.stack[this.stackPointer] = this.pc; // Store PC at stack + this.stack[this.stackPointer] = this.pc + 2; // Store PC at stack this.stackPointer++; // Increment it - this.pc = opcode & 0x0FFF; // Go to that address to execute code + let address = opcode & 0x0FFF; + this.pc = address; // Go to that address to execute code + } break; case 0x3: { // 3XNN // Skips the next instruction if VX equals NN - let val = opcode & 0x00FF; //0x00NN - if(this.regs[nib2] == val){ + if(this.regs[nib2] == secondOpcode){ this.incrementPC(); } this.incrementPC(); @@ -151,8 +189,7 @@ class CPU { case 0x4: { // 4XNN // Skips the next instruction if VX NOT equals NN - let val = opcode & 0x00FF; //0x00NN - if(this.regs[nib2] != val){ + if(this.regs[nib2] != secondOpcode){ this.incrementPC(); } this.incrementPC(); @@ -177,7 +214,7 @@ class CPU { case 0x7: { // 7XNN // Adds NN to VX - this.regs[nib2] = secondOpcode; + this.regs[nib2] += secondOpcode; this.incrementPC(); } break; @@ -204,37 +241,40 @@ class CPU { this.incrementPC(); }else if(nib4 == 0x4) { // 8XY4 - // Vx += Vy + // Vx += Vy, Set VF to carry let sum = this.regs[nib2] + this.regs[nib3]; - this.regs[0xF] = sum > 255 ? 1 : 0; // Set carry flag this.regs[nib2] = sum & 0xFF; // Get only the first byte + this.regs[0xF] = sum > 255 ? 1 : 0; // Set carry flag this.incrementPC(); }else if(nib4 == 0x5) { // 8XY5 // Vx -= Vy - this.regs[0xF] = this.regs[nib2] > this.regs[nib3] ? 1 : 0; let subs = this.regs[nib2] - this.regs[nib3]; - this.regs[nib2] = subs; + this.regs[0xF] = this.regs[nib2] > this.regs[nib3] ? 1 : 0; + this.regs[nib2] = subs & 0xFF; this.incrementPC(); }else if(nib4 == 0x6) { // 8XY6 // Vx >>= 1 - this.regs[0xF] = this.regs[0xF] & 1; // ???? // Store the least significant bit of VX prior - this.regs[nib2] >>= 1; + // Stores the least significant bit of VX prior to the shift in VF + // Then. Shift Vx by 1 to the right. + this.regs[0xF] = this.regs[nib2] & 1; // Get the least significat bit + this.regs[nib2] = this.regs[nib2] >> 1; this.incrementPC(); }else if(nib4 == 0x7) { // 8XY7 // Vx = Vy - Vx - this.regs[0xF] = this.regs[nib3] > this.regs[nib2] ? 1 : 0; let subs = this.regs[nib3] - this.regs[nib2]; this.regs[nib2] = subs; + this.regs[0xF] = this.regs[nib3] > this.regs[nib2] ? 1 : 0; this.incrementPC(); }else if(nib4 == 0xE) { // 8XYE // Vx <<= 1 - // Set VF to 1 if the most significant bit of VX prior to that shift was set - this.regs[0xF] = this.regs[0xF] >> 3; - this.regs[nib2] <<= 1; + // Set VF to 1 if the most significant bit of VX. + // Then shift to the left Vx + this.regs[0xF] = this.regs[nib2] >> 7; + this.regs[nib2] = (this.regs[nib2] << 1) & 0xFF; this.incrementPC(); } @@ -253,14 +293,16 @@ class CPU { case 0xA: { // ANNN // Sets I to the address NNN - this.indexReg = opcode & 0x0FFF; + let address = opcode & 0x0FFF; + this.indexReg = address; this.incrementPC(); } break; case 0xB:{ // BNNN // Jumps to the address NNN plus V0 - this.pc = this.regs[0] + opcode & 0x0FFF; + let address = opcode & 0x0FFF; + this.pc = this.regs[0] + address; } break; case 0xC: { @@ -380,7 +422,7 @@ class CPU { // FX55 // reg_dump(Vx, &I) // Stores from V0 to VX in memory starting at address I. - for(let i = 0; i < nib2; i++) { + for(let i = 0; i <= nib2; i++) { this.memory[this.indexReg + i] = this.regs[i]; } this.incrementPC(); @@ -388,7 +430,7 @@ class CPU { // 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++) { + for(let i = 0; i <= nib2; i++) { this.regs[i] = this.memory[this.indexReg + i]; } this.incrementPC(); @@ -396,6 +438,9 @@ class CPU { } break; } + + if(this.delayTimer > 0)this.delayTimer--; + if(this.soundTimer > 0)this.soundTimer--; // Should I play a sound??? }