Added sound

This commit is contained in:
Miguel Angel 2024-09-06 12:43:07 +02:00
parent a56d787878
commit e6bdded35e
4 changed files with 120 additions and 18 deletions

View File

@ -27,6 +27,7 @@
<script>
const emulator = new Revuelto8ts.Chip8Emulator();
const emulatorCanvas = document.getElementById('emulator-screen');
let fullDirRoms = [
'./roms/1-chip8-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
View 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;

View File

@ -1,17 +1,21 @@
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;

View File

@ -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();
}
}