From 13e41e69f7a10b819f77c2db0b9e5364ea51de2e Mon Sep 17 00:00:00 2001 From: Can Date: Mon, 3 Feb 2025 17:12:20 +0100 Subject: UI changes and audio support --- src/cpu.effekt | 3 + src/main.effekt | 2 - src/renderer.effekt | 3 + src/renderers/js.effekt | 285 ++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 270 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/cpu.effekt b/src/cpu.effekt index d61d33b..c2a929e 100644 --- a/src/cpu.effekt +++ b/src/cpu.effekt @@ -389,6 +389,9 @@ def makeCPU() {r: Renderer} = { } if (sound.toInt() > 0) { sound = (sound.toInt() - 1).toByte() + r.beep() + } else { + r.stopBeep() } last_timer_update = currentTime diff --git a/src/main.effekt b/src/main.effekt index 59f8f12..befe021 100644 --- a/src/main.effekt +++ b/src/main.effekt @@ -7,7 +7,6 @@ import bytearray def main(): Unit = { // Using the JS backend - region global { def renderer: Renderer = JSRenderer::makeRenderer def cpu_ = makeCPU() {renderer} def plsRender(rom: ByteArray): Unit = { @@ -16,6 +15,5 @@ def main(): Unit = { } renderer.init(plsRender) () - } () } \ No newline at end of file diff --git a/src/renderer.effekt b/src/renderer.effekt index 9aca29d..0e8145b 100644 --- a/src/renderer.effekt +++ b/src/renderer.effekt @@ -7,6 +7,7 @@ Every backend must implement this interface. */ import bytearray +// region of runtime interface Renderer { def init(run: (ByteArray) => Unit at {io, global}): Unit @@ -17,4 +18,6 @@ interface Renderer { def update(f: () => Unit at {io, global}): Unit def log(msg: String): Unit def getKeyPressed(): Option[String] + def beep(): Unit + def stopBeep(): Unit } diff --git a/src/renderers/js.effekt b/src/renderers/js.effekt index 05802e6..3292481 100644 --- a/src/renderers/js.effekt +++ b/src/renderers/js.effekt @@ -13,6 +13,8 @@ extern io def log(msg: String): Unit = jsWeb "log(${msg});" extern io def loadRom(): ByteArray = jsWeb "rom ? rom : new Uint8Array(0)" extern io def requestAnimationFrame {callback: () => Unit}: Unit = jsWeb "requestAnimationFrame(() => $effekt.runToplevel((ks) => ${box callback}(ks)))" extern jsWeb """ + let audioContext = null; + let oscillator = null; let rom = undefined; let keyStates = new Map(); // Change to track multiple keys let lastKeyUpdate = performance.now(); @@ -60,31 +62,246 @@ val pageContent = """ Effekt8 + -

Effekt8: Chip8 Simulator written in Effekt Language

- - - -
- -
-
-

Logs:

-

+      
+
+

EFFEKT-8

+

CHIP-8 Emulator in Effekt

+
+ +
+
+ + +
+ + +
+ +
+ +
+ +
+
+

CONTROLS

+
+
+
1
+
2
+
3
+
4
+
+
+
Q
+
W
+
E
+
R
+
+
+
A
+
S
+
D
+
F
+
+
+
Z
+
X
+
C
+
V
+
+
+
+ +
+

SYSTEM LOGS

+

+          
+
+ - """ @@ -159,6 +376,30 @@ extern io def getKeyPressed(): String = jsWeb """ })(); """ +extern io def stopBeep(): Unit = jsWeb """ + (() => { + if (oscillator) { + oscillator.stop(); + oscillator.disconnect(); + oscillator = null; + } + })(); +""" + +extern io def beep(): Unit = jsWeb """ + (() => { + if (!audioContext) { + audioContext = new (window.AudioContext || window.webkitAudioContext)(); + } + if (!oscillator) { + oscillator = audioContext.createOscillator(); + oscillator.type = 'square'; + oscillator.frequency.setValueAtTime(440, audioContext.currentTime); // 440Hz = A4 note + oscillator.connect(audioContext.destination); + oscillator.start(); + } + })(); +""" namespace JSRenderer { // make JS Renderer def makeRenderer: Renderer = new Renderer { @@ -173,5 +414,7 @@ namespace JSRenderer { val key = getKeyPressed() undefinedToOption(key) } + def beep() = beep() + def stopBeep() = stopBeep() } } -- cgit v1.2.3