![]()
I created Bunny Semiconductor (Itch.io, source code) for the Free-Software Purism Game Jam 2024. It's the first game jam I've done since 7 Day Roguelike 2018.
This is the first finished project I've had in a while that I can show and talk about.
Origin of the idea
I have been thinking more about computer hardware since I worked on Raspberry Pi bare metal. I started dipping my toes in to PCB layout last month, which led me to begin researching semiconductor manufacturing.
I got interested in manufacturing in general after reading Dan Wang's How Technology Grows (a restatement of definite optimism) (Archive). I had been prepared for these ideas from one of my favorite talks, Jonathan Blow's Preventing the Collapse of Civilization.
In order to live by this idea that manufacturing is important, not just something to leave to China, I started making physical things at Open Works in Baltimore. This is a satisfying break from my typically software-heavy interests, and finishing physical useful things feels awesome.
My career has been in software, so with my dabbling in manufacturing I of course have an interest in slowly bridging the gap–both using software to design hardware (or e.g. run CNC machines), and building hardware that I program with my software. The bottom of the hardware "stack" which software eventually runs on is of course the integrated circuit. As I started learning about how these are made, I kept craving a game or simulation that would help me "see" what I was learning so that I could gain an intuition.
I originally wanted the game to be a more accurate simulation, or more educational, because I wanted to learn more about semiconductor manufacturing. It ended up being enough work just making a simple factory simulation that I ran out of time to do more accurate educational material.
My father worked for many years in semiconductors at Signetics, National Semiconductor, and Fairchild Semiconductor. As a child I never understood what he did, but as an adult I admire his involvement in this immensely impactful industry. I borrowed one of his textbooks on semiconductor manufacturing, but admittedly did not have time to integrate much of what I read in the game.
Semiconductor manufacturing intrinsically offers interesting gameplay–problems with yield need to be isolated and improved; machines need to be tuned; economic trade-offs between die size/complexity, price per product, number of employees, cost of machines, etc. can be optimized; and systems design around parallel processing, pipelines, buffers, etc. directly apply to fab design. This game was a chance for me to use the real world as an inspiration rather than other games, as Raph Koster recommends (archive). I ultimately had to fallback to extremely simple and familiar game mechanics due to the short time frame, but I still believe this field inspires rich gameplay opportunities.

Getting help
Art has always been my weakness in my game projects, so this jam I committed to asking for help from others.
My older brother Duke made the 3D models. My wife Vivian drew the four views of the bunny workers and two-frame walking animations.

Vivian's best friend Daisy illustrated everything on the title screen based on a rough mock-up I gave her. I had to do some extra math work to get the tilted IC buttons on the main menu to work, but I really liked the extra fun style they added.

I wanted the illustration and overall style to be cute and casual as a nice contrast with the highly technical subject matter. My brother complained that almost all the real-world fab machines he used for reference were just big white boxes. I think he took great creative liberties in exaggerating the operations to make the machines look fun while still paying homage to their real world equivalents.

My personal favorite, the Etching acid bath.
These contributions enhanced the game immensely, and I am thankful for them. I would not have a chance of winning without their art.
Result
I won 1st place in the jam out of 6 entries. I had the following scores:
Ranked 1st with 5 ratings (Score: 3.950)
| Category | Rank | Score | Raw Score |
|---|---|---|---|
| Gameplay | #1 | 3.800 | 3.800 |
| Art/Graphics | #1 | 4.400 | 4.400 |
| Overall | #1 | 3.950 | 3.950 |
| Theme | #2 | 4.200 | 4.200 |
| Audio/Sound | #4 | 3.400 | 3.400 |
I ran out of time to make original music for the jam, so I ended up using music from my first album. I recorded all the sound effects quickly, but only ended up with a couple viable ones. The other participants recognized that the audio wasn't my strength this jam. The sound does make a big impact on the tactility of the game, so I am glad I got it in, even if it was a rush job.
I am of course pleased with winning. I entered the jam expecting there would be few competitors given what I imagine is a small target audience: people interested in a privacy-focused Linux phone who also make games and have time to do game jams. I was gunning for top 3 in order to get the prize phone.
Things did get hairy half way through when several life events happened:
- A wedding took up an entire weekend; I did zero work on the game.
- I got sick and wasn't able to work for another 3 days or so.
- The in-laws visited for two weeks. "Family comes first" so I couldn't work as hard as I may have.
The last three days were where I had to really pull the game together. I made the dialog system the second to last day, which ended up making a huge impact on the playability and polish of the game.

I stayed up late to wrap up the final pieces and submitted only 50 some odd minutes before the deadline–I was up until about 2:30 am.
Other entries
It was great to see the other entries. Jams where no one can use Unity or Unreal must be few and far between these days. Overall everyone was positive and put in clear effort both creating and trying the other games. I was also pleased to see everyone hosting their code on e.g. Codeberg rather than the closed platform Github.
I was especially impressed by Hurry Curry, which is looking to be an open-source implementation of Overcooked, a game I greatly enjoy playing with my friends. I had performance issues with the client, but the developer already suggested they are working on it:
[…] We used rust for server and godot with gdscript for our client and now have performance unsuitable for mobile. Therefore I am currently creating a new client right now, also using SDL2 and Rust only, while minimizing dependencies too.
Technical details
Bunny Semiconductor is written mostly in a single 5,000 line Cakelisp file.
I made a platform abstraction because I wanted to try to not rely on SDL for this game, but I did not have time to make the EGL Wayland platform. I wrote about this in the forum (Archive):
An update: I was going down the rabbit hole of trying to static link the entire game. It's proving to be about as hairy as one would expect–I've got Musl LibC static linked, now I'm attempting to build Mesa and LibDRM from source to avoid the libGL dynamic load.
For now, I'm going to focus on making the game, and then come back to the lean setup. I need to make sure I have something worth playing before I work on what it's built on.
I have a "Platform SDL" that wraps all the SDL code, and I hope near the end of the jam to replace it with a "Platform Wayland Static". If I run out of time on that I'll still have a game which uses SDL and runs on the phone.
And my overall feelings on developing for the Librem 5:
Overall the Librem 5 wasn't too bad to develop for. There are three things that created more work than a regular Linux desktop:
- The portrait/landscape/fullscreen never quite worked how I wanted it to. I ended up just telling the user "Turn your device to landscape" rather than doing the too costly refactor of the game to work in portrait.
- OpenGL ES 2.0 is a bit limiting. I had to de-instance my GL code as well as port my GLSL to GLSL ES. Framerate seemed to be okay; when the models are large on-screen the librem dips to 50 hz, but normally it sticks to 60hz.
- The phone gets hot very fast while the game is running. I would love to hear what the Purism devs suggest I do on my end to fix this. I could frame-cap to 30 hz instead, which would be worth it if it makes the game playable for long periods rather than overheating in maybe 15-20 minutes.
My work on Cakelisp continues to pay dividends. I used my GameLib utilities to be up and running with 3D models and various other things.
User interface
I am happy with how my user interface programming went on this project. I have written several simple immediate-mode UIs (archive), but none have felt good enough to reuse. This iteration is my best yet. I had several functions for setting the cursor baseline proportionally, by pixel, and by 3D coordinate, which resolved many of my layout troubles I encountered with my past IMGUIs. My text wrapping was also dead simple: I would sensibly set the left wrap-to position automatically when the baseline was set, then explicitly set the wrap-at point when necessary.
This one notably had a simple immediate-mode animation system that worked quite well for sprinkling in that extra animation, which added polish. The API looks like this:
(im-animate-id
(im-pane)
(addr (path s-im-state > offset-x)) (addr (path s-im-state > offset-y))
anim-ease anim-direction-upwards)
(defer (im-pane))
(im-set-font font-heading)
(im-set-cursor-baseline-font-relative 1 1 im-relation-top-left)
(when (im-button "Staff")
(set-ui ui-state-hud))The (im-pane) call just returns a unique ID for the "stack" of widgets that frame. The offset-x and offset-y directly influence the placement of any of the elements created by the im- functions. These offsets are a fixed value such that it could actually act as an ID rather than rely on the im-pane, but I found it was useful to use the im-pane direct ID so I could refer to it later (to e.g. restart a description pane animation when you select an item without changing UIs).
I remain convinced that immediate mode UIs are the Way. Even with the limited time frame I was able to make useful debug UIs thanks to the ease of IMGUIs.
Simulation and saving
The simulation happens in a single function, game-simulate. While thinking of how workers actually accomplish the task of following the recipe to create the products using the fab, I realized that it made the most sense for the wafers themselves to drive the process. Wafers know what state in the process they are at. If they are in a machine which will perform their desired next stage, they will sit tight; otherwise, they will post a job for the next available worker to pick up. The workers simply carry wafers from one machine to another as the wafers request. This wafer-centric view made any need for planning or pathfinding unnecessary.
The relationships system was added on the last day, but it was important because it was the primary tie-in for the jam theme, symbiosis. I managed to scrape it together but didn't get the chance to make it very balanced. I was happy to hack in the "Share employee" action for the Schools relationship by making a new job type that simply made the worker walk to the world origin 0, 0 and do a fixed amount of "research". I thought this was a great quick solution that is also cute since you see your workers trudging away to "school".
I made the game on a fixed grid with lanes because 1) it made placement simpler and 2) it meant I could tune the lanes so that the billboarded worker sprites wouldn't clip too terribly with the models. It had the nice side-effect of actually matching what real fabs look like, which tend to be multiple long lanes of machines.
I'm very pleased with the game load/save of my game. I put everything in a single plain old data structure which made saving and loading as simple as a fwrite and fread. I hooked it up to my versioning system and basically had compatible saves throughout development.
I did this partly because I have been annoyed by Playdate games not having separate profiles. I frequently share my playdate with Vivian, so if the game only has one profile we have to reset the game so she can play it from the beginning (and I lose my progress).
Conclusion
This is the first 3D game I've completed for a game jam without using any engine. I definitely feel I have leveled up significantly in the last few years. My Cakelisp technology no doubt delivers value both in my happiness and my productivity.
I probably won't be doing another jam for a while since they are a good deal of work and stress for me, but I did have a fun time!