Minesweeper-nw banner

Minesweeper-nw

17 devlogs
28h 20m 24s

Minesweeper-nw is a Minesweeper game for the Numworks calculator, written in Rust (no_std/bare metal / NO OS). It runs on embedded hardware with approximately 100KB of RAM (heap and stack combined) on a Cortex-M7.
Due to severe screen tearing, th…

Minesweeper-nw is a Minesweeper game for the Numworks calculator, written in Rust (no_std/bare metal / NO OS). It runs on embedded hardware with approximately 100KB of RAM (heap and stack combined) on a Cortex-M7.
Due to severe screen tearing, the LCD cannot be fully redrawn every frame, even though the CPU is powerful enough. This required implementing a custom “dirty rect” or partial redraw system to update only the necessary areas (:
There is no pre-existing game or UI engine, i had to code everything myself while dealing with the screen’s constraints. However.
I made sure to avoid hardcoding as much as possible, designing the whole system to be (in my opinion) quite modular and well-structured.

This project uses AI

I’m using Gemini to translate documentation and to ask about how game engines and UI systems work.

Demo Repository

Loading README...

Oignon

I’ve documented the optimization techniques used in the app.

Attachment
0
Oignon

v1.2.2 - Statistics!

I’ve added a statistics and scoring system to the game!

It does exactly what you’d expect: it tracks your wins, losses, and average play time, while keeping Normal and Hard modes separate.

Of course, all stats are saved, so you won’t lose your data when closing the app (:

Aside from that, I did some refactoring here and there, minor tweaks, etc.


This is officially the last content update for the game. It’s finally feature-complete!

Attachment
0
Oignon

I was fed up with hardcoding text display in the menus, so I refactored the entire menu rendering system. To do this, I built a component rendering module with a simplified Layout system.

I probably over-invested in this new system, it was a huge sink in terms of time and brainpower, but I truly hated how I was handling UI text before.

Attachment
0
Oignon

v1.1.0 - The States saving!

This version introduces a game state saving system! When you quit the game while in the middle of a match, it is automatically saved. As soon as you relaunch the game, it reloads and you can continue playing as if nothing happened. Your game time will not be affected.

This is very useful, especially if you are working on your Hard Grid and suddenly need to calculate 1 + 1well, you can now exit the game, do your math, and come back. Or, if you don’t want anyone to see you playing Minesweeper, you can close it without losing your current progress.


The principle is simple: when you exit the game, it saves all the important parameters of the current match into a minesweeper_game.sav file. Then, when the app launches, if the file exists, the data inside is loaded.

Technically, this feature was not easy to implement at all! Fortunately, I had already planned the game’s structure from the beginning to potentially add this feature, which saved me from having to build something flimsy or rewrite part of the engine.

I realized there was an error, there was a dummy version of the file-reading functions in eadkp (the lib I wrote and am using here), so I ended up doing some bug hunting.

In any case, this was an addition I was dreading, but it all came together nicely in the end, so it’s all good (:

0
Oignon

v1.0.0

First version of Minesweeper for the Numworks calculator.

New features:

  • Added a rust.yml workflow to automatically include the compiled package (NWA) in every release and tag.
  • Added a README (you just gotta have one).
  • Added a LOGO (I didn’t have one yet ¯_(ツ)_/¯ ).

Test video on the real hardware! (It worked on the very first try!)

0
Oignon

I added explanatory text and the final time to the EndGame screen. I also added a ‘Hard’ mode with the largest possible grid (small cells and 15% mines).

Attachment
Attachment
0
Oignon

I added a timer and the theoretical number of remaining mines.

Attachment
0
Oignon

I added the title bar rendering for both the game and the main menu. I also refactored part of the code for these bars and moved the rendering functions into a separate file.

Attachment
Attachment
0
Oignon

I improved a few details, like centering the grid on the screen, fixing the main menu text alignment, and adding a background to the main menu.

I also made some code improvements, such as reducing memory fragmentation by eliminating unnecessary heap allocations and deallocations whenever possible.

0
Oignon

I added the Game End screen (won and lose). Also, when you lose, all the mines are revealed.

0
Oignon

I’ve implemented the system that reveals all empty tiles (I don’t know what this system is called, but there you go).

Next step: the Game Over system!

0
Oignon

I added mine rendering

0
Oignon

I’ve added the main interactions (reveal, flag). I also fixed a bit-shift bug in how I was storing the number of adjacent mines, as well as a bug in the randint function of my eadkp library used here.

0
Oignon

So, you can’t tell just by looking at it, but I’ve written the state management code and the cell display logic (which was more complicated than expected!).

I’ve also coded the cursor movement. Now, I’m going to tackle the interaction system.

0
Oignon

I added:

  • Background rendering
  • Cell margins
  • Different cell rendering based on size (large or small)

And fixed:

  • Cell sizing
0
Oignon

I am currently creating a Minesweeper game for the Numworks calculator.

Well then! It turns out I might have forgotten to install Wakatime in my
Docker container, so a good portion of my coding time wasn’t tracked ):
You can easily add at least 2 more hours to the total.

First off, I spent 2 days thinking about the code structure. Since there’s
no engine, no multi-threading, and especially some nasty screen tearing
that forces me to only update what’s necessary, I can’t redraw the whole
screen every time (that’s my main constraint).

First, I coded a State system to manage what to render (menu, game,
game over). Then, I built an event-driven graphical rendering pipeline.
Everything works through a shared object, allowing all components to
access the same data (position, score, etc.).


I admit the current rendering isn’t great (I forgot the background
instruction, sorry), but you’ve got to have the vision! This is literally
the first test render (by the way, my code worked in only two tries,
which is remarkable).

0