In Defense of Game Developers, and The Public Misconception about .kkrieger

Rama Alifiandy
10 min readApr 30, 2021

On 23 April 2021, a YouTuber by the name of Nostalgia Nerd made a video about .kkrieger, the fabled 96 KB FPS game, and it’s a fantastic and well-made documentary about the technical achievement the demoscene people had made.

You can give it a watch here:

The fantastic documentary about .kkrieger, including direct quotes from the developers. © Nostalgia Nerd

However, the comment section of the video (and other YouTube videos covering .kkrieger) brought up a common misconception, talking about how .kkrieger achieved something playable in something so “little”, when other games, especially in recent years, reached 1048576 times larger size. In summary, here’s what people of general gamer public thought about it:

If .kkrieger could achieve playable 3D game in 96 KB, why not any other games do the same?

This kind of naive mindset disturbs me, mainly because I’m developing a game myself and know the inner workings of games. So, I decided to write this article, getting into why the magic isn’t as practical as you want to believe. Hopefully, it’ll at least reduce the misconception about the game and game file sizes in general.

Disclaimer: This article is NOT implying that .kkrieger by itself is subpar product. Don’t get me wrong, .kkrieger is a marvelous technical achievement, however, there are compromises made to get there, and there are valid reasons it’s not a common practice in game development.

Playable FPS on 96 KB

Well, sort of.

.kkrieger is a playable first person shooter video game developed by a popular German demoscene group Farbrausch in 2004, deployed with a modified, interactive version of their .werkkzeug engine. The group already gained popularity among the demoscene community with their outstanding procedural 64 KB demo achievements. You can get it from the Pouet page here.

The procedural warrior in action, shooting procedural baddies. © Farbrausch / .theprodukkt

What makes this game stands out is that the entire game is stuffed inside a single 96 KB Windows executable! No additional files or dependencies in the same folder, all of the assets and code are stuffed inside the single executable.

You asked to yourself, in fascination upon playing the game, “How did they do that?”

All The Stuff in 96 KB

Remember the “sort of” sentence in the previous section? Now we’re going behind the magic curtain of the game.

Under the hood, everything in .kkrieger is completely procedural. From the sound, the textures, and even the models. The non-existent of pre-baked assets is what makes the 96 KB dream possible. The non-interactive version of the .werkkzeug engine is available for download at the Pouet page, and I’ll be using it to demonstrate some of the techniques used in the game.

Procedural Textures

To create the textures, .kkrieger generates them procedurally from a predefined creation history, and also making use of Windows font system. Basically, the CPU has predefined list of things to do in order to create a texture. This creation history data has much, much smaller storage footprint than a heavily crunched JPEG image stuffed inside an aggresive ZIP compression.

For example, let’s say we want to generate a texture for a sheet of plywood. In .werkkzeug, we can generate a bunch of dots, give it a directional blur, then distort it with a noise texture, and map the monochromatic colours into something close to a plywood. We can also use text rendering to create textures. In this case, we create a couple of letter O and a zero using Arial font, which is common in Windows installations. After that, we can mix both textures into one with another distortions, to create uneven distortions. There is a reason why we have to choose Arial or other common Windows font, but we’ll get into it in the caveats section.

Creating plywood texture out of blurred pixels and texts with .werkkzeug.

This kind of texture generation is a common practice in small sized demos, and in some ways, even deployed in practical game production. But we’ll get into the caveats later.

Sculpting by Math

The meshes in .kkrieger is also built procedurally with the same method, but this time, by modifying primitive meshes. Those primitive meshes are cubes, tori (plural of torus, not to be confused with 鳥), spheres, and cylinders. As with the textures, the meshes also leaves very small storage footprint, and because it works best on abstract shapes, it lends to the shared look between small demo peers.

Going back to .werkkzeug, we can create an abstract sculpting by taking a primitive and modify its vertices accordingly, and apply procedural texture we made prior.

A sculpt piece made out of primitives and math.

.werkkzeug also support hierarchical animation to be applied on mesh, again, with the same method, and it’s been used for .kkrieger as well. Although setting it up is rather finicky.

Clash of Waves

The audio used in .kkrieger is also procedurally generated chiptunes, using basic waveforms that are mixed and processed in real-time to create more rich sounding instruments, while also being smaller than even a small MP3 file.

This way of creating sound isn’t exactly unheard of. Many 8-bit and Sega Mega Drive games already deployed this kind of technique, but if you want to be specific to 3D games, Square Enix also did the similar thing, deployed in their lesser known PlayStation 1 game, Vagrant Story. Almost all of the sound effects in it, except voice snippets, are generated by manipulating waves and noises, and adding reverb effects on top of it.

Squeeze Every Last Byte

If you think about file compression, you may point to the ZIP format, but .kkrieger, along with other small demos, deploys a more sophisticated method than that.

Other small demos managed to squeeze astonishing procedural graphics, in part thanks to a compressor called Crinkler. Unlike ZIP or self extracting archives, Crinkler is a compression linker used to crunch down already small executable files even further upon compiling. With Crinkler, one can fit a demo down into 1 KB, enough to be printed as QR code! However, shortly before Crinkler released to the public, Farbrausch already deployed their own compressor, called .kkrunch, and it’s also used to squeeze .kkrieger down to 96 KB.

Of course, with the game being crammed into 96 KB, there are few caveats present throughout.

The Catch of Being 96 KB

There are few compromises that had to be made and limitations imposed to get into 96 KB size mark. The first thing is that the game demands high processing power and memory capacity, and it’s quite high even in 2004. A crappy Windows XP machine you have lying around might have troubles running the game. There are reasons why the game isn’t being modest with hardware requirement, even if the executable is just 96 KB.

Inflates Like A Rubber Pool

People are naively assuming that the game’s RAM usage won’t be that far from 96 KB numbers. Well, all the procedural content has to be stored somewhere to be loaded by the GPU at all times, right?

Once executed, the program will generate all the assets out of the creation history data, and store them all in RAM, exploding from 96 KB up to around 310 MB. This was huge back in 2004, when contemporaries like DOOM 3 uses around 256 MB of RAM.

Crunching Even More Math

The CPU also has the job to interpret the creation history data into usable textures and meshes, and the load time will be depending on CPU thread count instead of the storage read/write speed. Threadripper wasn’t a thing back in 2004, so the load times are quite long with the average hardware configuration of that era.

There are minor bugs like having the main menu unable to move up, but I don’t think it’s a deal breaker in the grand scheme of things, so I won’t get through them.

8-bit Games Below 96 KB

Before we get into the recent year, let’s take a 30 years leap back to the 80s.

It was the 1980s. The decade of boxy cars, weird puffy hairstyles, bulky CRT television sets, IBM PCs, floppy disks, red book CD audio, VHS that reign supreme over Betamax, and Nintendo’s Family Computer console, which brought back the faith of North American industry towards video game with its Nintendo Entertainment System (NES) rebranding.

The Chronicles Of Italian Plumber in 40 KB

One of the best selling games for the Famicom was Super Mario Bros. A platformer video game developed and published by Nintendo in 1985, the entire game is contained inside a single bank 40 KB ROM, including all the sprites/artwork, the game code, the levels, and the sounds.

An Italian plumber turned national hero is on his way to take down a giant reptile. © Nintendo Co., Ltd.

The game only have handful of unique art assets, 32 unique levels sharing the same assets with predefined palette swaps, not much lines of text and letters, simple gameplay loop, handful of unique sound effects, and 14 unique music tracks. Given those factors, it was enough to fit on 40 KB ROM containment.

Too Quick To Reach The Limit

However, there was a problem. Even in 1985, two years after the Famicom debuted in Japan, third party developers wanted to fit more content and gameplay inside their Famicom games, but couldn’t, due to Famicom’s 40 KB ROM limit imposed upon them. Therefore, Nintendo came up with memory mappers to allow Famicom games to be larger than 40 KB (some games are even as big as 1 MB). Without those limit removing memory mappers, we wouldn’t have groundbreaking Famicom games by now, even subsequent Super Mario Bros. games.

In Defense of 96 GB

Now that the true 8-bit days are gone, let’s go to the current year of true 64-bit. Where games barely fit a single 50 GB Blu-ray disc.

In defense of game developers, there are valid reasons why games can go larger than 50 GB in size, and not following .kkrieger’s methods.

Cheap Loading Done Quick

We all know that RAM has blazing fast read/write speed, but its price rate for every single GB is also way more expensive than non volatile storage medias. As of 2021, 8 GB of RAM has the same price range to 1 TB of HDD or 240 GB of SSD. Not everyone outside enterprise server maintainers have system RAM larger than 128 GB.

Even if 128 GB of RAM is somehow accessible to everyone, we would still have to generate all the materials and textures procedurally. In order to do that, the CPU will have to work on generating those assets before running game threads, thus increasing load times even more than games being read on the shoddiest 1x CD reader drives. Not to mention that RAM is a volatile memory. One you close the game or restart the computer, you will have to endure the long load times all over again, shall you want to play again.

But what’s a 3D environment without lighting? Not everyone have real-time raytracing capable GPU (and yes, I care a lot about low-spec gamers) and generating lightmap can took a long, long time. We’re talking about minutes, so the load time would be even longer. Even software only low resolution GI tracers for quadratic polys can take 3 or so minutes to generate.

Abstract Is Not For Everyone

Primitive manipulation deployed by small demos are best for abstract geometries, but creating something more than demoscene product can be more daunting procedurally than just premade the asset.

Generating humanoid characters procedurally, just using math and primitive manipulation, is borderline impossible. The time and manpower would be best used to create artistic character models, instead of coming up with imprecise math algorithm to get a shoddy looking character model. Not even folks at Shadertoy have yet to get a good looking, production ready, full body human model from primitive manipulations alone — the most accurate human head Shadertoy project, pictured below, still uses predefined vertices, not by primitive manipulations. And let’s not get into clothing, animating, and voice acting said characters.

We’re still far away from creating believable human characters with math alone. © Thomas Schander

Sound effects generated by waveform manipulation can only go so far to create incidental sounds, from explosions, footsteps, to magic sounds. And don’t get me started with ongoing brigade against AI based voice acting, which the technology itself is still occupies large space on disk for the learning data and requires powerful CPU to generate.

Conclusion in Less Than 96 KB

Love it or hate it, the way games are shipped now is the most efficient method, by putting all the pre-made stuff into the storage, give it a bit of compression, so that the RAM could focus on loading the necessary assets instead of storing all the assets, and the CPU could focus on executing game threads instead of procedurally generate the assets, thus reducing load times. Not to mention the advancement in SSDs, cutting down load times more while still being reasonably inexpensive.

While .kkrieger shows that it’s possible to cram a playable FPS into 96 KB of executable, it’s more of a novel technical achievement than something that you would play for hours. And it’s still a remarkable achievement, it deserves to be a part of UNESCO’s cultural heritage of Germany (and the rest of Europe).

--

--

Rama Alifiandy
0 Followers

An independent game developer using Unreal Engine 4. Previously modding Doom.