HN
Today

Ported my C game to WASM, here's everybug that I hit

The author meticulously documents the numerous technical hurdles, from 32-bit pointer woes to OpenGL ES strictness, encountered while porting a C game to WASM. This practical guide resonated with Hacker News, sparking discussion on WASM's 32-bit limitations, its potential to bridge web and native, and persistent developer frustrations with its ecosystem. It's a candid look at the nitty-gritty of cross-platform development that exposes subtle architectural assumptions.

27
Score
14
Comments
#5
Highest Rank
7h
on Front Page
First Seen
Jun 15, 11:00 AM
Last Seen
Jun 15, 6:00 PM
Rank Over Time
139519222028

The Lowdown

The author, 'birdculture', shares a detailed account of porting their custom C game, "Match Morphosis," to WebAssembly (WASM) using Emscripten. The post serves as a practical guide, meticulously documenting the non-obvious bugs and challenges encountered, offering solutions that could save other developers considerable pain.

  • Debugging Hurdles: The need to revert to Visual Studio for 32-bit native debugging, as WASM uses a 32-bit address space, making it a crucial step for replicating and fixing WASM-specific bugs locally.
  • 32-bit Pointer Mismatches: The most significant issue was the incompatibility of 64-bit structs containing raw pointers when running on 32-bit WASM, leading to incorrect struct layouts and data corruption. The solution involved decoupling runtime data from serialized asset data to eliminate pointers from packed structs.
  • Accidental 64-bit Correctness: A subtle bug where sizeof(ThingHandle*) coincidentally equaled sizeof(ThingHandle) on 64-bit systems masked a memory allocation error that only surfaced on 32-bit WASM due to differing pointer sizes.
  • OpenGL ES Strictness: The author found WebGL (based on OpenGL ES) to be far more stringent than DirectX regarding graphics pipeline configurations, requiring precise vertex layout declarations, exact component count matches in shaders, and Y-axis flipping for framebuffers.
  • Shader Compilation & GLSL Specifics: Transitioning from HLSL to GLSL ES for web required shader recompilation and addressing syntax differences (e.g., lerp() vs mix(), strict float literals like 0.0 instead of 0).
  • Emscripten & Web Audio Quirks: Overcoming browser autoplay policies for audio and an obscure Emscripten issue where miniaudio required explicit export of HEAPF32 to function correctly.

The author expressed satisfaction with the porting process, noting that Emscripten proved solid and most difficulties arose from assumptions that worked by accident on 64-bit Windows but were exposed by WASM's 32-bit environment.

The Gossip

Bit-Size Bafflement

Many commenters questioned why WASM is primarily 32-bit, expressing surprise and frustration at encountering old pointer-size issues. The discussion highlighted that while a `memory64` proposal exists, 32-bit remains common due to historical design (related to Asm.js) and a performance advantage in bounds checking, as a 4GB address space allows for simpler virtual memory reservations without performance penalties.

Web's New Frontier or Folly?

There's a clear divide in sentiment regarding WASM. Some hail it as a revolutionary bridge between web and native programming, fostering better hardware awareness and attracting native developers to the web platform. Others express disappointment, pointing out persistent limitations like the lack of direct DOM manipulation, inadequate WASI (WebAssembly System Interface) for POSIX-like features, and the continued reliance on JavaScript "glue" and bundlers, drawing parallels to past failed browser plugin technologies.

C Code Conundrums

A few comments touched on best practices for C code portability and potential security implications. One commenter offered an alternative, more robust syntax for `sizeof` in memory allocations to prevent common pointer-size-related bugs. Another warned that porting C code to WASM inherently carries over C-based vulnerabilities, referencing academic research on the topic.