2026 SNESDEV Game Jam devlog 1
I'm taking a break from my games and audio driver to prototype a game for the 2026 SNES DEV Game Jam (1st August to 1st November 2026).
My entry is open-source and will be published on GitHub.
Committing goals to a blog post
The game jam started badly for me. There was lots of procrastination, uncertainty and a major lack of urgency - I cannot focus when there's a vague and undefined goal months in the future. To help motivate me throughout this project, I spent some time brainstorming well-defined goals for the jam.
I'm typing them out and committing them to this blog post to hopefully internalise them.
-
Build and maintain healthy snesdev habits.
I want to snesdev every day and build up a consistent and steady progress towards a very long-term goal.
I want to avoid my current bad habits of indecision paralysis, constant distractions, procrastinating the start of sub-projects and taking short breaks that end up multiple hours or days.
I'm planning on assigning a 2 or 3 hours of free time every day to work on the game jam. I'm also attempting to document when (any why) I get distracted and/or loose focus in the hopes future-me can quickly recognise when I procrastinating and get back on track.
-
Document what I'm doing as I do it.
My writing skills are terrible and have badly atrophied from instant messaging, a journal that's mostly dot points and microblogging platforms (with their limited message length). I do want document what I've done but when I try to sit down and type I end up staring at a blank page for 15 minutes. By the time I have the motivation to document a subsystem or release months have passed and the memories are no longer fresh in my head.
A blog post by Brennan Kenneth Brown suggests I start writing 200 words a day, every day. I have not been able to reliably do this but I am getting better at it. Hopefully in the next few weeks, I'll have written a few thousand words that would be useful for my blog.
-
Make a demo-game with a 65816 C compiler.
I'm curious about the current state of 65816 C compilers. In recent years a few 65816 C compilers have been published and I'm interested to see how well they perform. I understand they will be not be anywhere near as efficient as the assembly code I can slowly write, but I hope the C code will be faster to write and a lot easier to edit. Most of the game will be written in C, with minimal assembly functions where speed and efficiency are required. I'm hoping that only the MetaSprite rendering, VBlank interrupts, audio APUIO transfers will be in assembly.
Last year I offered to test JCC816. I was originally going to write up a short single screen puzzle game but the game jam provided the perfect excuse to try something more ambitious.
The game currently targets 3 different C compilers (JCC816, llvm-mos and vbcc) so I have a fallback C compiler and can continue game development if I encounter a major game-breaking bug in JCC816.
-
Relive the 1 game a month experience I had back in 2015.
Before I attempted to make a full SNES game, I started snesdeving with 11 small (and badly balanced) prototype games. Each month I started with a new hardware feature or design pattern and used it to make a small game. Sometimes I reused subsystems I had written in previous months, usually the MetaSprite and entity handling code. Some of the subsystems I wrote back then were only used once, but I did learn from each and every one of them.
So far, this goal has been going horribly. I have 4 or 5 different ideas on how to tackle sprites and (until recently) could not decide which one to use.
For this game jam, I need to quickly decide on a design and stick to it. It doesn't matter how well it works, it only needs to work.
-
Prototype a moving platform design and see if it will be useful for Space Rescue Squad.
Moving platforms will greatly improve the level variety and add new challenges to Space Rescue Squad. However, I do not know if the platform design I have recently scribbled on loose A5 paper is viable or not. More importantly, modifying data structures in tightly integrated low-level assembly is stressful as I always feel like I'm going to break something.
I'm going to prototype the moving platforms design in a simplified platform game written in C. Writing and changing data structures and algorithms is a lot easier in C. If my design turns out to have a major issue (like bad tile/platform/player collision interaction), I'll know in a few days of C coding instead of a week of assembly coding.
-
Prototype enemies and platforms moving on a global timer/cycle.
This is something I haven't done before and I am wondering how difficult it would be to implement.
At the end of September, if I feel like I'm running low on time I'll drop this goal and switch to my traditional independent enemy design to ensure I release a mini-game by jam's end.
My original goal (back at the start of the year) for the game jam was to quickly make a small game in a month and spend the next two months polishing it. I had wanted to gain experience in adding effects and graphical niceties to a game before I start improving the graphics of Space Rescue Squad and unnamed-snes-game. In hindsight that goal was unrealistic and I'm not in the right head-space for rapid coding and complex graphical effects.
Lots of procrastination, not a lot of progress
Regretfully, I started the game jam late. Other projects and events felt more important than the game jam and a feeling of "I'll start it tomorrow" was overwhelming my intended goal of "doing a little bit every day is better than a crunch session every week".
For instance, I spent a lot longer than I liked trying to brainstorm ways of mixing 65816 C code with already written assembly (having an engine call C code and C code calling engine functions). None of this is useful for the game jam. I was trying to see if I could prototype Space Rescue Squad enemy behaviour in C before potentially writing it in assembly code. It's not a viable idea - the memory layout and calling conventions between the C compilers and untech-engine are highly incompatible and requires a lot of careful compatibility layer. It's too much work for very little reward.
So far I have the toolchain setup, the VBlank interrupt handler written and a way to DMA resources in Work-RAM and the PPU.
I also have a rough outline of the MetaSprite and map subsystems (covering the inputs, compilation steps, ROM data formats and process steps). It was difficult, I kept thinking "what if" and "how about" and couldn't focus on a single design. After I realised I was going in circles, I committed to a simple design that should be easy to implement (even if it bare-bones and not something I would use for a full-game).
Resources subsystem
It's took many days (including a few days of decision paralysis) to design a way of embedding resource data into the ROM. Most of the complexity came from me targeting 3 different C compilers, each with their own different way of adding data.
I saw two different ways I could do this:
- Write a python script that takes a list of resources to generate 3 different
.incbin/#embedsource files for each C compiler. - Write a python script that packs the resource data into the ROM after the code has been compiled + linked by the C compiler.
I chose the second option, mainly because it would speed up rebuilding the game whenever a level or graphic has changed (by skipping the C recompilation step).
My toolchain reads a resources.txt list containing resource names and generates a gen-enums.h file containing the resource ids (so the C compilers and insert-resource.py use the same resource index mapping). The C code contains a blank RESOURCES_TABLE array which is used to populate DMA registers.
struct ResourceTableEntry {
uint16_t size;
uint16_t addr;
uint8_t bank;
};
const struct ResourceTableEntry RESOURCES_TABLE[N_RESOURCES] = {0};
inline static void populate_dma_regs(uint8_t id) {
DMA_DAS0 = RESOURCES_TABLE[id].size;
DMA_A1T0 = RESOURCES_TABLE[id].addr;
DMA_A1B0 = RESOURCES_TABLE[id].bank;
}
After the C code is compiled and linked, insert-resources.py will pack the resources into data banks, append them to the end of the ROM and populate the RESOURCES_TABLE array (using the symbol file to get the table address).
Naturally, this did not work the first time. jcc816 worked nicely. llvm-mos and vbcc65816 was outputting garbage. vbcc was writing 0's to the DMA registers (I think it realised RESOURCES_TABLE is 0 initialised and constified the array access) and llvm-mos was always loading resource id 0 (I think it decided all entries in the RESOURCES_TABLE are identical and optimised-away the indexing).
My solution to this problem - rewrite the code that copies the RESOURCES_TABLE data to the DMA registers in inline assembly. It took a few hours to figure out the syntax (as there aren't many examples to work off) and it works nicely.
This issue, the compiler optimising away resource reads, is not going to be a major problem for me. I've decided the resources are going to loaded directly into PPU memory or Work-RAM (into a global variable for more efficient access) and not accessed via pointers. It might affect future MetaSprite rendering code, I'm not sure how much of that will be written in assembly.
The resources subsystem also supports loading a fixed-sized resource header to Work-RAM before populating the DMA registers with the remaining resource data. I'm currently using it to determine the size of the tilemap in a image resource (so an image resource holds tile and map data), it will be useful the upcoming MetaTile subsystem.
What's next?
I have planned out the various subsystems of the game. If I am to make a game by the end of October I will need to have made some progress in all of them by the end of September.
Arrows dictate functions/data required by each subsystem.
Subsystems with a * star have multiple instances (ie, each enemy is a different entity instance).
I'm aiming to have the Map, MetaSprites and basic player movement code completed in the next two weeks. I've already written multiple instances of these subsystems, so I already know what I have to do. The hardest part will be maintaining focus and keeping everything simple and basic.