diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5219bd7 Binary files /dev/null and b/.DS_Store differ diff --git a/chip8_core/target/.rustc_info.json b/chip8_core/target/.rustc_info.json index f4e163d..ce0264d 100644 --- a/chip8_core/target/.rustc_info.json +++ b/chip8_core/target/.rustc_info.json @@ -1 +1 @@ -{"rustc_fingerprint":9251509361105874613,"outputs":{"12016735552878863467":{"success":true,"status":"","code":0,"stdout":"rustc 1.93.0 (254b59607 2026-01-19)\nbinary: rustc\ncommit-hash: 254b59607d4417e9dffbc307138ae5c86280fe4c\ncommit-date: 2026-01-19\nhost: aarch64-apple-darwin\nrelease: 1.93.0\nLLVM version: 21.1.8\n","stderr":""},"13822592305234237280":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/lukashammer/.rustup/toolchains/stable-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""}},"successes":{}} \ No newline at end of file +{"rustc_fingerprint":9251509361105874613,"outputs":{"13822592305234237280":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/lukashammer/.rustup/toolchains/stable-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"12016735552878863467":{"success":true,"status":"","code":0,"stdout":"rustc 1.93.0 (254b59607 2026-01-19)\nbinary: rustc\ncommit-hash: 254b59607d4417e9dffbc307138ae5c86280fe4c\ncommit-date: 2026-01-19\nhost: aarch64-apple-darwin\nrelease: 1.93.0\nLLVM version: 21.1.8\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/website/index.js b/website/index.js index de65f92..73b179d 100644 --- a/website/index.js +++ b/website/index.js @@ -1,3 +1,4 @@ + import init, * as wasm from "./wasm.js" const WIDTH = 64 @@ -28,17 +29,23 @@ class Chip8Sound { this.enabled = true; } - init() { - if (this.audioContext) return; + async init() { // Added async + if (!this.audioContext) { + try { + this.audioContext = new (window.AudioContext || window.webkitAudioContext)(); + this.gainNode = this.audioContext.createGain(); + this.gainNode.connect(this.audioContext.destination); + this.gainNode.gain.value = 0.1; + } catch (e) { + console.error("Failed to initialize audio:", e); + this.enabled = false; + return; + } + } - try { - this.audioContext = new (window.AudioContext || window.webkitAudioContext)(); - this.gainNode = this.audioContext.createGain(); - this.gainNode.connect(this.audioContext.destination); - this.gainNode.gain.value = 0.1; // 10% volume - } catch (e) { - console.error("Failed to initialize audio:", e); - this.enabled = false; + // Every time init is called via an interaction, try to resume + if (this.audioContext.state === 'suspended') { + await this.audioContext.resume(); } } @@ -183,18 +190,34 @@ Keybinds are explained inside the game. (German keyboard: Z is the Y key)` } -gameSelect.addEventListener("change", () => { - const value = gameSelect.value - descriptionBox.textContent = - descriptions[value] || "Select a game to see instructions." -}) +gameSelect.addEventListener("change", async function(evt) { + if (!evt.target.value) return; + + // Call this IMMEDIATELY before any 'await' calls + initAudio(); + + if (anim_frame != 0) { + window.cancelAnimationFrame(anim_frame); + } + + // ... rest of your fetch logic +}); // Initialize audio on first user interaction function initAudio() { - if (!audioInitialized && soundEnabled) { - sound.init() - audioInitialized = true - console.log("Audio initialized") + if (soundEnabled) { + sound.init(); + audioInitialized = true; + + // Create and play a tiny buffer of silence to "unlock" the audio hardware + if (sound.audioContext && !audioInitialized) { + const buffer = sound.audioContext.createBuffer(1, 1, 22050); + const source = sound.audioContext.createBufferSource(); + source.buffer = buffer; + source.connect(sound.audioContext.destination); + source.start(0); + audioInitialized = true; + } } } @@ -213,6 +236,10 @@ async function run() { chip8.keypress(evt, false) }) + document.addEventListener('touchstart', function() { + initAudio(); + }, { once: true }); + // Mobile touch keyboard logic const keyButtons = document.querySelectorAll(".key-btn"); @@ -251,6 +278,10 @@ async function run() { soundToggle.addEventListener("change", (evt) => { soundEnabled = evt.target.checked sound.setEnabled(soundEnabled) + // FIX #1: Initialize audio on toggle interaction (helps mobile) + if (soundEnabled) { + initAudio() + } }) } @@ -297,6 +328,14 @@ async function run() { return } + // FIX #2: Validate file extension to prevent Rust aliasing error + const fileName = file.name.toLowerCase() + if (!fileName.endsWith('.ch8') && !fileName.endsWith('.c8')) { + alert("Invalid file type. Please upload a .ch8 or .c8 file.") + fileInput.value = '' // Clear input to prevent state pollution + return + } + descriptionBox.textContent = "No description available for uploaded files." // Reset the dropdown @@ -309,6 +348,8 @@ async function run() { chip8.reset() chip8.load_game(rom) mainloop(chip8) + // FIX #2: Clear file input after successful load + fileInput.value = '' } fr.readAsArrayBuffer(file) }, false)