Added sound
This commit is contained in:
parent
a56d787878
commit
e6bdded35e
44
index.html
44
index.html
@ -27,7 +27,8 @@
|
||||
|
||||
<script>
|
||||
const emulator = new Revuelto8ts.Chip8Emulator();
|
||||
|
||||
const emulatorCanvas = document.getElementById('emulator-screen');
|
||||
|
||||
let fullDirRoms = [
|
||||
'./roms/1-chip8-logo.ch8',
|
||||
'./roms/2-ibm-logo.ch8',
|
||||
@ -40,23 +41,56 @@
|
||||
'./roms/Maze[David Winter, 199x].ch8',
|
||||
];
|
||||
|
||||
// Set user keys
|
||||
emulator.setUserKey('1'.charCodeAt(0), 1); // 1
|
||||
emulator.setUserKey('2'.charCodeAt(0), 2); // 2
|
||||
emulator.setUserKey('3'.charCodeAt(0), 3); // 3
|
||||
emulator.setUserKey('4'.charCodeAt(0), 12); // C
|
||||
|
||||
emulator.setUserKey('q'.charCodeAt(0), 4); // 4
|
||||
emulator.setUserKey('w'.charCodeAt(0), 5); // 5
|
||||
emulator.setUserKey('e'.charCodeAt(0), 6); // 6
|
||||
emulator.setUserKey('r'.charCodeAt(0), 13); // D
|
||||
|
||||
emulator.setUserKey('a'.charCodeAt(0), 7); // 7
|
||||
emulator.setUserKey('s'.charCodeAt(0), 8); // 8
|
||||
emulator.setUserKey('d'.charCodeAt(0), 9); // 9
|
||||
emulator.setUserKey('f'.charCodeAt(0), 14); // E
|
||||
|
||||
emulator.setUserKey('z'.charCodeAt(0), 10); // A
|
||||
emulator.setUserKey('x'.charCodeAt(0), 0); // 0
|
||||
emulator.setUserKey('c'.charCodeAt(0), 11); // B
|
||||
emulator.setUserKey('v'.charCodeAt(0), 15); // F
|
||||
|
||||
document.addEventListener("keydown", function(evt) {
|
||||
emulator.keyDownEvent(evt.key.charCodeAt(0));
|
||||
});
|
||||
document.addEventListener("keyup", function(evt) {
|
||||
emulator.keyUpEvent(evt.key.charCodeAt(0));
|
||||
});
|
||||
|
||||
// Set audio
|
||||
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||
let volume = 0.02; // Volume between [1, 0] // Set it low if you don't want to become deaf
|
||||
emulator.startAudio(audioContext, volume);
|
||||
|
||||
// Load ROM
|
||||
fetch(fullDirRoms[3])
|
||||
fetch(fullDirRoms[6])
|
||||
.then(response => response.arrayBuffer())
|
||||
.then(arrayBufferRom => {
|
||||
let romData = new Uint8Array(arrayBufferRom);
|
||||
emulator.loadRom(romData);
|
||||
});
|
||||
|
||||
const emulatorCanvas = document.getElementById('emulator-screen');
|
||||
|
||||
|
||||
setInterval(function() {
|
||||
if(emulator.isRomLoaded()) {
|
||||
//console.log(emulator.getCPUStatus());
|
||||
console.log(emulator.getCPUStatus());
|
||||
emulator.emulateCycle();
|
||||
emulator.drawToCanvas(emulatorCanvas, 8);
|
||||
}
|
||||
}, 5);
|
||||
}, 60);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
41
src/audio.ts
Normal file
41
src/audio.ts
Normal file
@ -0,0 +1,41 @@
|
||||
class Chip8Audio {
|
||||
audioBrowserContext: AudioContext | null;
|
||||
oscillator: OscillatorNode | null;
|
||||
gainNode: GainNode | null;
|
||||
|
||||
volume: number;
|
||||
|
||||
constructor() {
|
||||
this.audioBrowserContext = null;
|
||||
this.oscillator = null;
|
||||
this.gainNode = null;
|
||||
this.volume = 0.1;
|
||||
}
|
||||
|
||||
startAudio(audioContext: AudioContext, volume: number) {
|
||||
this.volume = volume;
|
||||
this.audioBrowserContext = audioContext;
|
||||
this.gainNode = this.audioBrowserContext.createGain();
|
||||
this.gainNode.connect(this.audioBrowserContext.destination);
|
||||
this.gainNode.gain.setValueAtTime(this.volume, this.audioBrowserContext.currentTime);
|
||||
}
|
||||
|
||||
startBeep() {
|
||||
if(this.oscillator == null && this.audioBrowserContext && this.gainNode) {
|
||||
this.oscillator = this.audioBrowserContext.createOscillator();
|
||||
this.oscillator.type = 'square';
|
||||
this.oscillator.frequency.setValueAtTime(440, this.audioBrowserContext.currentTime); // 440 Hz (A4 note)
|
||||
this.oscillator.connect(this.gainNode);
|
||||
this.oscillator.start();
|
||||
}
|
||||
}
|
||||
|
||||
stopBeep() {
|
||||
if(this.oscillator) {
|
||||
this.oscillator.stop();
|
||||
this.oscillator = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Chip8Audio;
|
@ -1,18 +1,22 @@
|
||||
import CPU from './cpu';
|
||||
import Keyboard from './keyboard'
|
||||
import RNG from './RNG'
|
||||
import Chip8Audio from './audio'
|
||||
|
||||
class Chip8Emulator {
|
||||
cpu: CPU;
|
||||
keyboard: Keyboard;
|
||||
rom: Uint8Array;
|
||||
audio: Chip8Audio;
|
||||
|
||||
romLoaded: boolean;
|
||||
|
||||
constructor() {
|
||||
this.keyboard = new Keyboard();
|
||||
this.cpu = new CPU(this.keyboard);
|
||||
this.audio = new Chip8Audio();
|
||||
this.cpu = new CPU(this.keyboard, this.audio);
|
||||
|
||||
|
||||
this.rom = new Uint8Array();
|
||||
this.romLoaded = false;
|
||||
}
|
||||
@ -57,6 +61,14 @@ class Chip8Emulator {
|
||||
}
|
||||
}
|
||||
|
||||
setUserKey(userKey: number, key: number) {
|
||||
this.keyboard.setUserKey(userKey, key);
|
||||
}
|
||||
|
||||
startAudio(audioContext: AudioContext, volume: number) {
|
||||
this.audio.startAudio(audioContext, volume);
|
||||
}
|
||||
|
||||
keyDownEvent(key: number) {
|
||||
this.keyboard.userKeyPressedDown(key);
|
||||
}
|
||||
@ -64,9 +76,6 @@ class Chip8Emulator {
|
||||
keyUpEvent(key: number) {
|
||||
this.keyboard.userKeyPressedUp(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default Chip8Emulator;
|
36
src/cpu.ts
36
src/cpu.ts
@ -1,4 +1,5 @@
|
||||
import RNG from './RNG'
|
||||
import Chip8Audio from './audio';
|
||||
import Keyboard from './keyboard';
|
||||
|
||||
const SCREEN_WIDTH = 64;
|
||||
@ -24,11 +25,13 @@ class CPU {
|
||||
displayMemory: Uint8Array;
|
||||
|
||||
keyboard: Keyboard;
|
||||
audio: Chip8Audio;
|
||||
|
||||
|
||||
rng: RNG;
|
||||
|
||||
|
||||
constructor(keyboard: Keyboard) {
|
||||
constructor(keyboard: Keyboard, audio: Chip8Audio) {
|
||||
this.memory = new Uint8Array(MEMORY_SIZE);
|
||||
this.displayMemory = new Uint8Array(SCREEN_WIDTH*SCREEN_HEIGHT);
|
||||
this.pc = 0x200;
|
||||
@ -39,6 +42,7 @@ class CPU {
|
||||
this.soundTimer = 0;
|
||||
this.regs = new Uint8Array(REGISTERS);
|
||||
this.keyboard = keyboard;
|
||||
this.audio = audio;
|
||||
|
||||
this.rng = new RNG(0);
|
||||
|
||||
@ -249,8 +253,14 @@ class CPU {
|
||||
}else if(nib4 == 0x5) {
|
||||
// 8XY5
|
||||
// Vx -= Vy
|
||||
let subs = this.regs[nib2] - this.regs[nib3];
|
||||
this.regs[0xF] = this.regs[nib2] > this.regs[nib3] ? 1 : 0;
|
||||
let subs = 0;
|
||||
if(this.regs[nib2] >= this.regs[nib3]) {
|
||||
subs = this.regs[nib2] - this.regs[nib3];
|
||||
}else{
|
||||
subs = this.regs[nib2] - this.regs[nib3];
|
||||
//subs = 0xFF - subs;
|
||||
}
|
||||
this.regs[0xF] = this.regs[nib2] >= this.regs[nib3] ? 1 : 0;
|
||||
this.regs[nib2] = subs & 0xFF;
|
||||
this.incrementPC();
|
||||
}else if(nib4 == 0x6) {
|
||||
@ -258,8 +268,8 @@ class CPU {
|
||||
// Vx >>= 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.regs[0xF] = this.regs[nib2] & 0x1; // Get the least significat bit
|
||||
this.regs[nib2] = (this.regs[nib2] >> 1) & 0xFF;
|
||||
this.incrementPC();
|
||||
}else if(nib4 == 0x7) {
|
||||
// 8XY7
|
||||
@ -273,8 +283,8 @@ class CPU {
|
||||
// Vx <<= 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.regs[0xF] = (this.regs[nib2]) >> 7;
|
||||
this.regs[nib2] = (this.regs[nib2] << 1);
|
||||
this.incrementPC();
|
||||
}
|
||||
|
||||
@ -439,8 +449,16 @@ class CPU {
|
||||
break;
|
||||
}
|
||||
|
||||
if(this.delayTimer > 0)this.delayTimer--;
|
||||
if(this.soundTimer > 0)this.soundTimer--; // Should I play a sound???
|
||||
// Timers
|
||||
if(this.delayTimer > 0) {
|
||||
this.delayTimer--;
|
||||
}
|
||||
if(this.soundTimer > 0) {
|
||||
this.audio.startBeep();
|
||||
this.soundTimer--;
|
||||
}else{
|
||||
this.audio.stopBeep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user