diff --git a/.vscode/launch.json b/.vscode/launch.json index 254dbb6..7b6e4fd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "type": "firefox", + "type": "chrome", "request": "launch", "name": "Debug chip8 emulator", "reAttach": true, diff --git a/roms/1-chip8-logo.ch8 b/roms/1-chip8-logo.ch8 new file mode 100755 index 0000000..19c5cf3 Binary files /dev/null and b/roms/1-chip8-logo.ch8 differ diff --git a/roms/2-ibm-logo.ch8 b/roms/2-ibm-logo.ch8 new file mode 100755 index 0000000..677f227 Binary files /dev/null and b/roms/2-ibm-logo.ch8 differ diff --git a/src/chip8Emulator.ts b/src/chip8Emulator.ts index 8aa3620..51cfc50 100644 --- a/src/chip8Emulator.ts +++ b/src/chip8Emulator.ts @@ -1,20 +1,33 @@ import CPU from './cpu'; +import Keyboard from './keyboard' class Chip8Emulator { cpu: CPU; + keyboard: Keyboard; constructor() { this.cpu = new CPU(); - console.log("Called constructor for Chip8Emulator"); - console.log("oh y"); + this.keyboard = new Keyboard(); } - loadRomAndStart() { - // Load rom - this.cpu = new CPU(); - this.cpu.dosomethingcool(); - - // Start full emulator + loadRom(rom: Uint8Array) { + + } + + emulateCycle() { + // Fetch opcode + // Decode opcode + // Execute opcode + + // Update timers + } + + drawGraphics() { + + } + + setKeys() { + } } diff --git a/src/cpu.ts b/src/cpu.ts index 9209b9e..802a9ef 100644 --- a/src/cpu.ts +++ b/src/cpu.ts @@ -1,13 +1,96 @@ +const SCREEN_WIDTH = 64; +const SCREEN_HEIGHT = 32; + +const MEMORY_SIZE = 4096; +const STACK_SIZE = 16; + +const REGISTERS = 16; + class CPU { - flags: Number; + pc: number; + indexReg: number; + registers: Uint8Array; + delayTimer: number; + soundTimer: number; + + stackPointer: number; + stack: Array; + + memory: Uint8Array; + displayMemory: Uint8Array; + constructor() { - this.flags = 0; + this.memory = new Uint8Array(MEMORY_SIZE); + this.displayMemory = new Uint8Array(SCREEN_WIDTH*SCREEN_HEIGHT); + this.pc = 0; + this.indexReg = 0; + this.stackPointer = 0; + this.stack = new Array(STACK_SIZE); + this.delayTimer = 0; + this.soundTimer = 0; + this.registers = new Uint8Array(REGISTERS); + + this.clearMemory(); + this.clearDisplay(); + this.clearRegisters(); + + // 0x000-0x1FF - Chip 8 interpreter + // 0x050-0x0A0 - 4x5 pixel font set (0-F) + // 0x200-0xFFF - Program ROM and work RAM + this.setupFont(); } - dosomethingcool() { - console.log("Doing something really cool"); + clearRegisters() { + this.registers.fill(0); + this.pc = 0; + this.indexReg = 0; + this.stackPointer = 0; + this.delayTimer = 0; + this.soundTimer = 0; } + + clearMemory() { + this.memory.fill(0); + } + + clearDisplay() { + this.displayMemory.fill(0); + } + + + setupFont() { + // Using address from 050 - 09F ?? + let addressFont = 0x050; + + // Every character has 5 Bytes + const characters = [ + 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 + 0x20, 0x60, 0x20, 0x20, 0x70, // 1 + 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 + 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 + 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 + 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 + 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 + 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 + 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 + 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 + 0xF0, 0x90, 0xF0, 0x90, 0x90, // A + 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B + 0xF0, 0x80, 0x80, 0x80, 0xF0, // C + 0xE0, 0x90, 0x90, 0x90, 0xE0, // D + 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E + 0xF0, 0x80, 0xF0, 0x80, 0x80 // F + ]; + + this.memory.set(characters, addressFont); + } + + + + + + } export default CPU; \ No newline at end of file diff --git a/src/keyboard.ts b/src/keyboard.ts new file mode 100644 index 0000000..b2ad974 --- /dev/null +++ b/src/keyboard.ts @@ -0,0 +1,40 @@ +const KEYS = 16; + + +// Keyboard +// 1 2 3 C +// 4 5 6 D +// 7 8 9 E +// A 0 B F +class Keyboard { + keys : Uint8Array; + + userKeyboardMap: Map; + + constructor() { + this.keys = new Uint8Array(KEYS); + + // Used to check keys from the user event.keys + this.userKeyboardMap = new Map(); + } + + private setKey(key: number, pressed: boolean) { + this.keys[key] = pressed ? 1 : 0; + } + + public setUserKey(userKey: number, key: number) { + this.userKeyboardMap.set(userKey, key); + } + + public userKeyPressedDown(userKey: number) { + let keyVal: number = this.userKeyboardMap.get(userKey) ?? -1; + if(keyVal != -1) this.setKey(keyVal, true); + } + + public userKeyPressedUp(userKey: number) { + let keyVal: number = this.userKeyboardMap.get(userKey) ?? -1; + if(keyVal != -1) this.setKey(keyVal, false); + } +} + +export default Keyboard; \ No newline at end of file