Dino Dash
Northwestern CE 205, Winter 2023
View code on GitHub ↗︎- ARM Assembly
- VGA Graphics
- Game Development

A Chrome-Dino-style runner, written directly in ARM assembly for the DE1-SoC's ARMv7 (Cortex-A9) processor. No game engine or graphics library, just direct writes to the board's memory-mapped VGA pixel buffer and pushbutton input.
Features
- Gravity: the dinosaur's y-velocity is affected by gravity during a jump, rather than jumping in a fixed arc.
- Difficulty scaling: the obstacles' and background's scroll speed increases with each level.
- Power-up: running into a cake makes the dinosaur invincible for a short time.
- Scrolling background: the background is built from pixmaps and scrolled right-to-left to sell the illusion of running.
Controls
- Push button 0 to jump
- Run as long as possible without colliding with an obstacle
- Push button 3 to restart

How it's built
Toolchain and rendering — The game runs in CPUlator, an in-browser ARMv7/DE1-SoC simulator, assembled and linked for a Cortex-A9 target with the standard arm-eabi-as/arm-eabi-ld toolchain. There's no framebuffer library in between: every sprite, background tile, and score digit is plotted by computing a pixel's address directly from its x/y coordinates against the VGA buffer's base address and writing a 16-bit color value to it. The whole screen (dinosaur, obstacles, clouds, cacti, and the live score readout) is redrawn this way every frame.
Input — Pushbutton input is interrupt-driven rather than polled, so a jump or restart is caught as soon as the button is pressed instead of on the next polling pass.
Collision detection — Compares bounding boxes between the dinosaur and each obstacle type, with the hitbox padding on each edge tuned per sprite rather than using one generic box, since the cactus and cake sprites aren't the same drawn width.
Jump physics — A small state machine driven by the dinosaur's y-velocity and y-acceleration, both stored as struct fields. While rising, y-position decreases each frame; past the jump's apex, downward acceleration accumulates into velocity every frame until landing, at which point velocity and the jump flag reset to their initial values.
Debugging
The scrolling background was the hardest part to get right. Six background layers (two ground segments, three clouds, and the cake) each track their own x-position independently, decrementing it every frame and resetting back off-screen once they scroll past the left edge. One of those reset comparisons used an incorrectly defined hex value, which didn't show up as an obvious crash, just a visibly wrong reset point on one layer when the game was running. Finding it meant stepping through CPUlator's register and memory view frame by frame, watching each background sprite's position against its reset condition, until the mismatched comparison value stood out.

Result
View the gameplay demo below: