aetheryx / a9-game

Minesweeper in Assembly(*ish)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

a9-game

My submission for Bonus Assignment 9 of the Computer Organization course at the VU: Minesweeper in x86 Assembly

Video demo

out3.mp4

Implementation

The original lab assignment suggests using the gamelib-x64 project template to set up a bootable entrypoint providing graphics output and interrupt handlers for keyboard input. However, I'm on an M1 Mac, gamelib-x64 is not compatible with Rosetta's x86 emulation, and I didn't feel like setting up a VM for development.

So instead of using gamelib-x64, I used the Raylib library with C interop. While Raylib provides many high-level concepts (shapes, 2d textures, shaders), I'm not using any of these utilities to draw pixels; I'm using Raylib with the same restrictions as Mode 10H's 0Ch call. The exception to this is the audio implementation, which was a bonus anyway.

I did end up implementing some of these concepts myself - most notably, reusable bitmaps. I first drew the tiles in Piskel, so I could work on graphics visually instead of editing raw coordinates:

Baking the bitmaps into the executable seemed like cheating, so I had to represent them in source code somehow. I'd like to think I made things reasonably bearable with some GCC macros. Take a look at the flagged tile bitmap for example.
Anyways, each of these bitmaps are pre-computed into a 32x32x4 buffer, and then drawn to the screen buffer on demand. Alongside that drawing process exists the concept of pixel resolvers: to prevent needing to compute every bitmap variant (e.g. red/green/grey bombs), the tile renderer can take an address to subroutine that can override the pixel that is to be drawn, sort of like a lambda function. This way, I could render tile color palettes dynamically at runtime. See the bomb pixel resolver as an example.

With the renderer done, the game logic was surprisingly not as difficult. The different kinds of state (revealed, bomb, or flagged) each have their own sections in memory. This is because tiles can be in more than one state (e.g. a bomb that is flagged). The grid-state module exposes some utility functions to manage the different kinds of state for a given tile.
In terms of logic, one of the common things I had to do is execute some code for every tile adjacent to a given tile. This was another interesting use of a lambda subroutine: the generic_adjacent function, given the coordinates of a tile, executes a given subroutine for every adjacent tile. This made counting adjacent bombs quite simple. The recursive revealing algorithm that spreads through the grid revealing tiles on click is implemented similarly.

About

Minesweeper in Assembly(*ish)

License:MIT License


Languages

Language:Assembly 96.8%Language:C 1.4%Language:Shell 1.3%Language:jq 0.6%