Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion chip8_core/target/.rustc_info.json
Original file line number Diff line number Diff line change
@@ -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":{}}
{"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":{}}
79 changes: 60 additions & 19 deletions website/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import init, * as wasm from "./wasm.js"

const WIDTH = 64
Expand Down Expand Up @@ -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();
}
}

Expand Down Expand Up @@ -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;
}
}
}

Expand All @@ -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");

Expand Down Expand Up @@ -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()
}
})
}

Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
Loading