Hacker News new | past | comments | ask | show | jobs | submit login
Tetris-OS: An operating system that only plays Tetris (github.com/jdah)
314 points by cconger on April 21, 2021 | hide | past | favorite | 122 comments



This is cool, but I think it's misleading to call it an operating system. It's Tetris that runs without an operating system, which is to say, on bare metal, old school. Writing programs that run on bare metal is a cool and worthwhile thing to do, but calling any such program an "operating system" is confusing.

This probably sounds like I'm picking a nit, but I think it matters for the sake of newbies just starting to climb the learning curve and trying to understand what an "operating system" actually is. IMHO, the defining characteristic of an operating system is that it provides an environment in which to run other programs, ones that are not part of the operating system, and which may not even exist at the time that the operating system starts to run.


Alternatively, it's Tetris with bits of a minimal OS mixed in, just enough to support it, which is not unlike what a lot of OSs in embedded systems are like.

A lot of software was written in this format several decades ago, including many games:

https://en.wikipedia.org/wiki/Self-booting_disk

https://en.wikipedia.org/wiki/List_of_PC_booter_games

I think the boundaries are quite fuzzy; while something like the mask-ROM firmware in a 4-function calculator or microwave would probably not be called an OS by the majority of people, how about a router running Linux, or the RTOS used in a car's ECU? Moving up from there, DOS is clearly in the realm of an actual OS, then we have the locked-down mobile devices, and at the far end are the general-purpose PCs running Windows, Linux, macOS, and such.

Even at the "small end", a microcontroller running a firmware containing a single infinite loop that does stuff with the peripherals seems unlikely to classify as an OS; but what if you start adding dynamic memory allocation, coroutines/cooperative multithreads, filesystem code, etc.?


It's a Tetris unikernel


Yes, props to the developer for what they've done, but I am perversely disappointed that this isn't actually a complete OS - process scheduler, file system, TCP/IP stack, multiple user support, all the rest - that only runs Tetris.


I used a few operating systems that were considered "complete," in their time, without a TCP/IP stack or multiple user support. Come to think of it, I don't think they had process schedulers either


Well, if you are into exokernels, they wouldn't have a TCP/IP stack either.

(You'd have them in userland. Whether you count that as part of the OS or not, is a different question.)


The software in your washing machine begs to differ.


I don't think it is essential that there be a clear boundary between an OS and programs.

For example, you can have a Smalltalk-based OS, written in Smalltalk. The OS components are simply Smalltalk classes and methods. Your programs/utilities/applications would also be Smalltalk classes and methods. There needn't be any clear boundary between the classes/methods that belong to the OS and those that belong to programs/applications/utilities.

If you look at library operating systems, the operating system is just a library which you link into your application. Such an operating system can only run one program, and you have to rebuild the operating system whenever you want to change the single program it runs. Still, I think library operating systems count as operating systems. This Tetris implementation isn't using a library operating system, but you could refactor the code into two parts – the Tetris game, and generic OS services, and the later would constitute a library operating system. If you look at its source files, only about seven of them (main.c, music.[ch], sound.[ch], speaker.[ch]) actually implement the game. The other 23 source files are generic OS services. So I'd say that, even if this isn't an operating system as a whole, it contains an OS within itself.


I like to define an OS as something that can execute arbitrary binaries. So if your hypothetical Smalltalk OS has a defined executable format that non-Smalltalk programs can compile to, I’d call it an OS.

Note that this also makes for example the uppermost part of the JVM an OS by my definition. I’d argue it’s not a completely incorrect characterization.


I think that definition is a bit too broad and too narrow to be useful.

For too narrow: you might have a security focused OS that includes everything like a TCP/IP stack etc, but perhaps doesn't allow arbitrary binaries by construction. (Eg it might only allow binaries that come with a proof of innocence, or some other restriction that's harsh enough to lose the 'arbitrary' rating.)

For too broad: https://en.wikipedia.org/wiki/Weird_machine would make almost any software that was written sloppily enough into an OS.


Obviously, "capable of running arbitrary binaries, but with a check inside exec() to allow only specific binaries run" counts as "capable of running arbitrary binaries".


Yes, perhaps a more specific example would be better.

Imagine some embedded application, eg in car, that has a network stack, graphics drivers etc, but can only run built-in functionality.


You've presented a conscientious criterion for what can be classified as an operating system. I think it's clever, I'm not sure I agree though. It's very broad: By this same definition any processor is an operating system, since it will execute arbitrary binary data. Your example of the JVM being an operating system calls to mind the above: It is a virtual machine, it is designed to execute arbitrary bytecode in a similar manner to a processor.


You may have found a loophole in my specification :) I’d like to amend it to specify that an OS refers to software “that can run...”. (And this is why we do design reviews!).

In your example, a real or virtual machine’s load/setregs interface is an operating system. One that can only run a single program at a time in the case of the physical processor’s bootstrap, but you’d be surprised how similar that is to early DOS.

A more hand-waving version is “the lowest level interface over the machine that can run...”. So a processor and a ROM grid can run arbitrary programs, but the lowest common denominator entry point is the ROM flashing spec! A very slow scheduler indeed.


What do you mean by "arbitrary binary"? Surely, you don't mean that absolutely any binary blob should be a meaningful executable. Because that would mean that my computer doesn't have an operating system because it's only capable of running binaries built for Ubuntu on amd64 -- if your binaries targeting BSD on ARM can be viewed as "arbitrary," then surely they shouldn't be expected to run on my pseudo-operating system.

No, every operating system that I know of makes some assumptions about the language that programs are written in. On my amd64/Ubuntu system, the language is largely specified by the processor (and, yes, has a binary format) and the programs are allowed to assume the presence of various devices, formats of various system calls, etc. Other languages are supported through a complicated system of compilers, interpreters and assemblers.

Or, coming at a different tack: does the existence of a C->Smalltalk transpiler turn the Smalltalk-based pseudo-OS into a real OS? What if the pseudo-OS doesn't ship the transpiler, and you need to run that yourself in user-space?


I don't agree that something has to be capable of running "arbitrary binaries" to count as an operating system. If I have a Smalltalk-based OS which is capable of running arbitrary Smalltalk code, but doesn't have any support for running non-Smalltalk binaries (native code or programs written in languages other than Smalltalk), I'd still consider it to be an operating system.


The “arbitrary” part is a force of how rather than what programs are run. Is your Smalltalk code running by compiling it into the OS? Is it loaded as a library? Can I write a C backend to output an indistinguishable library? In the latter cases, it is still capable of running arbitrary code - you may just be choosing not to.


You can still write code in a different language like C that will compile into Smalltalk VM bytecode. You will never be able to run any arbitrary code, just the one compiled for your machine. And in this case, the machine is virtual (but does not need to be). Symbolics Lisp machines were able to run Pascal as well, for example.


I somewhat agree with the sentiment, but I think the line is fuzzy. UNIX, as the stories go, originated as essentially an abstraction layer for a single video game, all written in assembly, and eventually expanded to have process isolation and a shell. So I'm inclined to think that this could be an OS, as it has to provide subroutines and code to drive hardware and provide an environment for the game to run, an "operating system" if you will.

But if you accept that, everything becomes fuzzy. Is the firmware an "operating system" then? The CPU microcode? On systems like the XEROX Alto, the microcode was developed like a sort of OS kernel. I think it's interesting to explore the "lesser meanings" of terms like "operating system" :-)


IDK. Plenty of "operating systems" are linked as a single binary with the application, in the embedded world and historically. This takes it a bit further but I doubt you think the dividing line is "OS and application are maintained as a separate project" which is about the only distinction.

I do see where you're coming from, though. Personally I would've described it as "bootable Tetris".


Even in embedded systems, there's still usually a distinct boundary between the OS kernel and the "application", and a well-defined API between the two.



There's an OS alright, it's just not a -general purpose- OS but a very small, statically embedded, specialised one.


It's no more misleading than saying it runs on bare metal. If I flash the correct motherboard ROM chip with the necessary bits to play Tetris in the UEFI (or completely replace it), would I be running closer or farther from "bare metal" than this is? Am I still on bare metal if I choose to use GRUB for loading up the game? Do I become an OS if I use GRUB instead of embedding that logic within my binary?

We call things BIOS and Boot-loader and Operating System by virtue of history, not necessity. It could even be confusing to a newcomer looking into development closer to the hardware and being told that all these programs are fundamentally different, instead of just being instructions and data getting shoved through a bunch of tubes in the processor and PCB.


That might be what OS'es currently _are_, but I disagree that it is what an OS _is_. I think fundamentally an OS is as the OP uses it, a set of code that interfaces with all your hardware to make the computer function.

Heres a good talk I came across in a HN comment a little while back [1] about how games used to be developed vs how they are today.

[1] - https://www.youtube.com/watch?v=kZRE7HIO3vk


It's not even running on bare metal.


I agree, but "operating system" is very poorly defined. Name a feature of an operating system and you can find one that doesn't support it. Just about the only definition that seems to hold is that it runs without an operating system.


That's a catchy hook but terribly misleading!


So if you could write programs with the tetris blocks, it'd be an OS? Sign me up!


You mean Minecraft?


If Apple and Google can release operating systems that can only run software which has been built for those platforms, approved by Apple/Google, and released through official delivery channels, this could be an operating system too, which only allows you to run program which have been pre-approved, possibly only to deliver blocks. Perhaps the keys are shortcuts to launch additional programs which change the wallpaper in various ways.


I made one too, 20 years ago! http://pliki.danieljanus.pl/btetris.bin

(Use qemu-system-i386 -fda btetris.bin if you want to try it out.)

Not really an OS, I just squeezed an implementation of Tetris into a 512-byte boot sector. I remember that a first draft had ~600 bytes and I was cutting away bytes, here replacing mov ax,0 with xor ax,ax, there reusing code as data, until I arrived at that size.

I've lost the source code, but ndisasm should help out.

I remember I encoded tetromino shapes as a 4x4 1bpp bitmaps taking up 2 bytes each, and there's a 56 41 59 41 52 01 56 01 15 48 52 41 59 in the hexdump, which in ASCII reads VAYAR^AV^A^UHRAY. I've been meaning to write a short story featuring a Vayar V. Hray as a protagonist, but never got around to it.


“In the 1980s with things like the Amiga computer, for example, every game was a boot disk. It booted into its own customized version of an operating system that ran what it needed to run to make its game work well and be performant and reliable. … We know that in the past, hardware that was very capable and very interesting made it so easy to create an operating system that literally everybody did it. Not a few people. Not even most people. But literally everybody.”

– Casey Muratori in “The Thirty Million Line Problem” https://youtu.be/kZRE7HIO3vk?t=1205


> It booted into its own customized version of an operating system that ran what it needed to run to make its game work well and be performant and reliable

Most bootdisk-based games did not have any kind of "customized version of an operating system". They were running on bare metal. For 99% of the games, there was no abstraction/management layer between the application (the game) and the hardware nor any kind of framework that would impose a certain structure on your application. Of course, game code was structured and you could often find subroutines for recurring tasks (clear screen, wait 100ms, read track from floppy,...) but even those were sometimes directly inlined in higher-level code (e.g. game AI) where it gave a performance advantage.

Only complex games had some kind of very thin abstraction/management layer that you could call an OS (often MUCH thinner than embedded micro-OS like RIOT or Contiki). As an example, Carrier Command had a quite general GUI system.


Also if you take 1 generation step back into the 2600 or intelivision there was a very simple API they did use that was built in. It was usually little more than fill out some memory in a particular way and flick an interrupt or particular instruction and it would either run something in bios or hardware. Also many did not need much in the way of an OS as they usually just either memory mapped themselves into the address space or copied themselves there. At that point if you keep your memory in order you do not need much and can toggle the registers yourself or call into bios routines yourself.

The newer machines use APIs to abstract. Where companies used to conform to particular HW standards (VGA,EGA,etc) with extensions. Now HW companies see their drivers as a differentiator. While the programmer writes to the abstraction API. Technically you could still write bare metal but few companies want to say what their real API looks like. So you are stuck with the OS or if you are lucky what someone else has noodled out.


The Atari 2600 has no BIOS or any other built-in ROM. Maybe you're thinking of the 5200 or 7800?


I was thinking more along the lines of fill in this memory set these registers and stuff happens. Which is not really bios but from a programmer POV it kinda acts like it (just in hardware). Like I pointed out it was a very simple API. Not even sure you could call it that. Re-reading what I wrote yeah I probably should have made that more clear. Intelivision did have a BIOS which they had to have because of the lack of chips they could get their hands on (mostly due to atari buying the capacity for locking out compettors).


I think Carrier Command (at least the PC version) was not a bootdisk game but a normal .EXE.


It should be again like this. I only truly understood C after I wrote my own fully functional Operating System (e.g. paging, interrupts, user mode, multitasking and multicore etc.) and got it running on bare metal. Programming other things in C now often feels like when you beat the final level in recent Mario games ("Champions Road") and replay the core game again, it just flows is easy and highly enjoyable.

I'd recommend every serious programmer to write their own OS.


>I'd recommend every serious programmer to write their own OS.

Um, I do extremely well working exclusively with higher level languages like Python and JavaScript. If we're talking about pure salary, a senior web dev will probably make more than the vast majority of embedded engineers.

I'm totally nitpicking here, but I don't like the gatekeeping of saying you need to be able to use a low level language to be a programmer


Without passing judgement on either side, I think the wording of your comment and the wording of the comment you're replying to speak for themselves. You mention you're talking about “pure salary”, while the comment you're replying to speaks about the enjoyment and knowledge brought about by understanding what's going on under the hood.

You may well have very different yardsticks. Programming means different things to different people.


How are we defining programming. As far as I'm concerned if I can create a small game using Unity, even if I don't really understand what's going on, that is programming.

If an intern writes a small Python script to format CSV contacts, that's programming. Programming can be completely visual as well, such as Unreal blueprints. I don't suggest going that route because it doesn't open up many career opportunities, but it still is programming.

Personally I've never been able to use a lower level language to get anything done. And I still have a fantastic career.


That was a recommendation, not a gatekeep.


I've wanted to do this but had some trouble finding a good reference. Do you have any resources you can share? Thank you! :)


The resource that got me started on this topic was: https://wiki.osdev.org/Main_Page

There's some decent tutorials available on here that provide a good introduction to the topic.


> It should be again like this.

OTOH the time of jumpers and dip-switches for configuring hardware state is over; I am not sure I want to give any gaming company any chance to persist not only in some management layer of my computer but also in peripherals.


Yet many of these self-booting disks would quite happily work when copied to a reboot-persistent RAM drive (the RAD: drive), which showed that although it was claimed that they did all the OS-ey things themselves, actually there was still quite a lot of the original OS still running there.

At the core of it, the AmigaOS exec was tiny and helpful, and things like device drivers were just separate processes that you sent messages to, so it would make sense to make use of them, but just not bother loading all the other stuff that makes up an OS.


Doesn't WHDLoad do that?


Yep.



He seems to forget that the Amiga had the OS in a ROM (or, in the case of the A1000, in a separate Kickstart disk to be loaded at power-up).

Boot-loaded Games disposed of the GUI (Workbench) and some other things, but the OS was not included in them.


Truly everything old is new again.


Youtube video that goes over the developer's experience making it: https://www.youtube.com/watch?v=FaILnmUYS_U


In my retirement, watching programming streams has been a guilty pleasure (drives my SO crazy), and this is one of my favorite channels. I especially loved their other video on making Minecraft from scratch*

* - https://www.youtube.com/watch?v=4O0_-1NaWnY


Wonderful! Mine has been chess streams. GMHikaru,IM Rosen, St. Louis Chess Club ... What else have you discovered?


Per Vognsen’s Bitwise (*) was one of my favorites until it was discontinued. It’s not a complete set, but still a great watch. I also enjoyed George Hotz’s occasional programming streams. He reminds me of some of my favorite colleagues from over the years.

I haven’t watched chess in a while, but your comment certainly sparked something. I may give it another go.

For a less nerd-y class of content, I have also enjoyed boxing videos - especially those focused on coaches illustrating technique.

[*] https://www.youtube.com/channel/UCguWV1bZg1QiWbY32vGnOLw


I just do this in between, for procrastination.


Replying to watch later!


You could also press on the timestamp of the message, which will present you with an option to add it to the list of your favorites, which you'll be able to access from your profile.



There is a similar project for Space Invaders here: http://www.erikyyy.de/invaders/


> Soundblaster 16 driver

This brings back memories for those wretched days when you needed floppy drivers for the most casual of peripherals. Life was simpler back then (and also much more complex)


If Tetris (with an infinite board) is Turing complete, then how about building an OS from Tetris?

(It seems for certain problems it is NP-complete!) https://liacs.leidenuniv.nl/~kosterswa/tetris/tot.pdf


If you already know that it's Turing complete, isn't it automatically also NP-complete?

(I also read the paper: to clarify, they are referring to different problems you can build on top of Tetris, and prove some of them NP-complete and some Turing complete.

(They don't mention Turing completeness directly, but they do a reduction to Post's correspondence problem.))


Right, my comment was the other way around; I don't know whether infinite Tetris is Turing complete.


Running a Turing machine reduces to Post's correspondence problem (which the paper shows reduces to answering some peculiar questions about Tetris).


Turing completeness refers to a language, while NP-completeness refers to an optimization problem.

So for it to be turing complete you first need to define a language based on tetris. For NP-completeness, it might just be solving the game.


Sorry to nitpick your nitpicking, but NP-completeness refers to decision problems (does there exist a solution with parameter k); optimization problems are often NP-Hard (find the minimum parameter k for which the decision problem has a solution).


You're right, sorry about the lack of precision


"Windows - Absolutely no idea."

QEMU works on WSL and WSL2 now, that would be one way.


QEMU works fine on Windows natively, and supports the "Windows Hypervisor Platform" as an accelerator ("-accel whpx" I think), same API that Hyper-V and WSL2 use. Where you might run into problems is the audio/video parts, not sure if QEMU can do audio on win32.

Edit: Thinking about it, I'm pretty sure QEMU comes with an SDL frontend by default, which should wrap at least audio output even on Windows.


Getting X and PulseAudio working is less than fun though... hoping MS or someone comes up with an "easy" button for that one. Managed to get X11 working, but not PulseAudio then kind of gave up on the experiment.


Looks like there's an easy button in the insiders channel now... will have to wait a while for GA though.


There's unofficial qemu binaries for windows that work without WSL.

https://qemu.weilnetz.de/


Couldn't you actually run this on bare metal on a suitable PC?


Or DOSBox. You could run the binary as if it was a bootable floppy.

          boot tetris.bin -l a
Or, if you have the source, change the org loading address to 100h, then compile it as usual, as DOS will see it as a COM file and thus you could run it under DOS.


I'm confused - doesn't qemu work fine on Windows natively?


He had specific command line switches for other environments, so it would allow the Linux example to "just work", other than maybe audio.

I'm sure someone could figure it out for Windows as well.


"Literally everything"

Love the brutal honesty.


I was half-expecting an OS where you delete a file by completing lines with the right Tetris pieces.


How would that work?

Genuinely curious, trying to visualize what you mean


Perhaps start with a set of blocks representing available resources. The 'top' equivalent could be a stream of blocks falling down the screen. Manipulate and rearrange the blocks to create new sets of blocks representing your desired function.

Deleting a file would be similar to any current GUI file manager, but with more blocks - drag file block to delete block. Opening a file with a particular program would be similar. Chaining a series of operations would be where it gets interesting. The shape of the pieces would control what can be chained together.


Damn that’s probably some good Tetris performance with it being so close to bare metal.

Edit: having read the readme, it looks like performance is locked at 60fps.


Reminds me of this https://www.nand2tetris.org/


How do we delineate "OS that does one thing" from "bare metal program?"


I'd argue that the difference is that an OS doesn't do just one thing, unless the thing is "run arbitrary other programs". (Which is to say, I think calling this an OS is a misnomer, since I don't see anything to suggest that it can load/run anything else)


I'm having enough difficulty separating "hypervisor" from "operating system".


meta-os, the os that runs the os. Then there is nested virtualization, and then user mode virtualization, so you can easily get 4 levels deep. Think of all the exits!


TetrOS would be a better name.



Another "TetrOS" (written in FASM): https://board.flatassembler.net/topic.php?t=21254


“Tetris” clones often seem to get aggressively shut down on copyright grounds too, so this might be more robust.


The name is a trademark, usually not calling it "Tetris" makes you measurably safer.

The tetrominos themselves are not protected but the shapes+colours are protected in some way (as original art), as is the official set of gameplay rules, the argument being that the overall combination of these is the "Tetris IP"... although the enforceability of that more often seem to hinge into "I don't have the money to fight an army of lawyers to prove that a gameplay idea isn't protected in yet another jurisdiction".

https://arstechnica.com/gaming/2012/06/defining-tetris-how-c...


Seems ironic since given the prominence of intellectual property theft from its creators in the Tetris story. :S


Maybe they learnt first-hand...


Except BSD games :p.


Would be interesting to make a bootloader and “OS” that you could wrap any game with, including GPU driven games like Crysis. I wonder how much more performance we could eek out of our hardware by removing extra overhead.


You don´t need Qemu, DOSBox will run it if you set 100h as the loading address.


> This has only been tested in an emulator. Real hardware might not like it.

?! So this is just a stand-alone binary with an awkward loader then.

The real trick (and challenge) comes when you want to run your stuff on actual bare metal.


I don’t understand your point? Are you trying to argue that OP didn’t work on a hard enough challenge to make you happy?


I'm arguing that OP did not build an OS. They built a program that needs a quite heavyweight runtime and loader in form of a system emulator.


Yeah... my biggest question is why it hasn't been tested on hardware. Dev doesn't own an x86?

Also the author refers to the (raw/MBR-format) disk image twice as an "iso" which makes me shudder.


If there was a floppy-based IMG file I would try it right out on bare metal.


Like the last bit. As many have observed a good movie is more about the sound than the sight.

But has it actually run on bare metal or just qemu I wonder. Anyway good music.


I am confused. Normally it's distributions that have an OS suffix. This is actually an Operating System. How rebellious.


if you built an operating system that only does X it’s called an embedded system or you know, a video game


Vertically Integrated Tetris!


I’d love to see a Super Mario Brothers version of this concept.


so this is just a bootable thing that runs Tetris? Does it do anything to run/control the hardware?


>Features:

> - It's Tetris.

Not sure what I was expecting.


I wonder why the choice of SB16


Because it's widely supported by emulators, and supports the 16 bit sample size at the 48 kHz sample rate that is needed for high quality music, which is more than enough for Tetris.

The SB16 also features FM synthesis, though this program doesn't appear to use it; it rolls its own wave table method.

However, that would be a particular reason to target it specifically, rather than some more modern card that lacks FM synthesis. FM synthesis produces the signature sounds heard in 80's pop music and video games.


non-PnP SB16 max out at 44.1KHz, only Vibra and later PnP models supported up to 48KHz.

The real reason is that SB16 is the lowest common denominator for DOS stereo compatibility with higher models. You might think SBPRo also supports stereo playback, but SB16, SB32, SB64, and SB128 do not support SBPro Stereo mode playback. SB16 DSP 4.x removed support for DSP 2.x 3.x "High Speed" modes. Anything using SBPro Stereo mode will not work in SB16 an newer at all.


probably because it's the least complex option which met the requirements.


Also because it’s supported by QEMU.


And any emulator since 1996.


Also can be natively enabled on bare metal by DOS without additional drivers, so many audio chips support(ed) SB16 long after DOS lost popularity.

Somewhat like VESA graphics modes which are at least there if you have no vendor-specific VGA drivers.


lol, this is awesome!


Well, at least until someone ports DOOM to it.


oh, so like emacs then?


Do you know that effect? Once you touch a topic, it appears to show up everywhere! :-) I recently wrote a tetris clone for braille users. https://news.ycombinator.com/item?id=26790812


Tetrinet next?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: