Size coding for the AVR

Here is a nice 778 byte program for a ‘Dino-runner’ clone:

and related blog discussion here.

Impressed even the OLED can be controlled with so little code!

2 Likes

There’s so little code that my brain can’t even comprehend it! How could a game be coded so simply?!

It genuinely doesn’t take much to control an OLED.

Setting it up takes a small list of commands, but after that it’s just a matter of piping a frame’s worth of data each time you want to update the display.

Also, bear in mind that AVR’s instructions are only 16-bits wide in most cases. A few are 32-bits wide, but the author seems to have dodged those (e.g. by using rcall instead of call).

The actual sprite rendering is the more impressive part. The fact the shrubs and digits are row-aligned makes them cheaper and easier to render, but it’s still respectably fiddly. The dinosaur is the more difficult one because it needs to have its representation bit-shifted and AVR is quite poor at bit-shifting due to the lack of a barrel shifter.

The score printing is also impressive in that it needs modular arithmetic to extract the digits and that has to be done ‘by hand’ with an algorithm because AVR doesn’t have a division circuit.

I expect this would actually be even shorter on ARM in thumb mode due to the native division, bit shifting, and the way ARM can branch every instruction. (No clue about x86 though.)

2 Likes

I’d love to try some size coded demo/ game for Arduboy… could be a neat Jam?!
At least fun to see a minimal framework to access buttons and screen on the Arduboy.
(But kinda the opposite direction to @bateske’s FX Jam…)

2 Likes

The problem there is that the people who know assembly would have an unfair advantage.

Also people would be trying to bypass the Arduboy2 library to get it smaller, thus taking away some of the safety nets.

Arduboy FX units would be fine because they boot into bootloader mode and have an easy way into the bootloader, but if a program got ‘stuck’ on an original Arduboy it might be hard to get off.

It might be alright to do with some strict ground rules.

You’ve basically just described the Arduboy2Core class:

https://mlxxxp.github.io/documents/Arduino/libraries/Arduboy2/Doxygen/html/classArduboy2Core.html

It’s all the low-level functions with no actual state. No drawing functions or screen buffer, just direct screen and button access.

(It hardly ever gets used in games, so people tend to forget it exists.)

1 Like

But from memory that’s many kilobytes?..

What is? Every single function in the class? Just the boot function? RAM or progmem?

I though the compiled code was kilobytes… but it was a few years ago I played with this…

We already did a jam for code size:

1 Like

Without specifics that’s doesn’t really hold much meaning.
Measuring code is a tricky pursuit for various reasons, and context is always important.

If that’s the number for every function then it’s hardly surprising because there’s quite a few of them, but hardly anyone is going to use every function. In C++ you don’t pay for what you don’t use, so any function that isn’t used won’t contribute to the final size.

Even then, you need to account for things like whether it’s being inlined or not to know whether what you’re measuring includes the actual calling code.

Some of the functions possibly could be made cheaper with pure assembly, but in most cases it’s not likely to be significantly cheaper because of how simple most of the functions are.

I think you’d be surprised at how good modern compilers actually are at optimising code. They actually do a lot of behind-the-scenes heavy lifting: building control flow graphs, rewriting code into static single-assignment form, careful register allocation, et cetera.

1 Like