back

rain in wasm

The raining ascii on my homepage was inspired by: soohoonchoi.com.

rules first

No libc, no libm, no allocation, no globals. The caller hands over a single block of memory, and a macro sizes it at compile time.

#define FIELD_BYTES(w, h)                          \
    ((size_t)(w) * (size_t)(h) * sizeof(float)     \
     + (size_t)(w) * sizeof(float)                 \
     + (size_t)(w) * sizeof(uint32_t)              \
     + (size_t)(w) * (size_t)(h))

the field

Each column is an independent stream of characters. I took a 32-bit hash of each column index to give it a permanent speed of 2.5-11 rows per second. A per-column accumulator collects speed * dt, and each time we cross 1, the column shifts down a single cell. Each cell gets multiplied by a decay factor so it fades as it falls.

The char entering at the top of the screen comes from hashing the column and its shift count in blocks of eight. The rain is a pure function of (seed, column, shift count).

freestanding wasm

No emscripten (because why not). The custom allocator is just a bump pointer starting at the address the linker marks as the end of static data:

extern unsigned char __heap_base;

static void *balloc(size_t n)
{
    uintptr_t p = (next + 15u) & ~(uintptr_t)15u;
    uintptr_t end = p + n;
    size_t have = __builtin_wasm_memory_size(0) * PAGE;

    if (end > have) {
        size_t pages = (end - have + PAGE - 1) / PAGE;
        if (__builtin_wasm_memory_grow(0, pages) == (size_t)-1)
            return 0;
    }
    next = end;
    return (void *)p;
}

Source: github.com/james-clarke/portfolio