For perspective, Atari 2600 had ROM cartridges starting at 2KB, and the machine itself had 128 bytes RAM. Considering that this game looks better than Atari 2600 Space Invaders, it seems like a pretty good job.
That's not really a fair comparison. The Atari didn't have any video memory, you drew by changing the color of the electron beam while it scanned the screen. It also had only 16 colors and a much lower resolution than what's being used here (maximum was 160x192 if you really tried).
In comparison, this game uses 320x200 with 256 colors (using 64k of video RAM). To draw a pixel on the screen, you just write a byte to the appropriate memory address.
Still, it's pretty impressive to write space invaders in only 512 bytes.
In this case, the BIOS'es contribution is fairly light:
- video mode change (int 10h, ah=0)
- RTC clock read (int 1ah, ah=0)
- keyboard read (int 16h, ah=0 and ah=1)
I am not familiar with Atari 2600 programming, but on the devices of that class:
video mode change would be at most few outb's, or omitted altogether if multiple video modes are not supported
"RTC clock" would be a loop waiting for VSYNC, likely less then a dozen operators
keyboard/joystick will be a simple "inb" at the core. It may, however, require debouncing, making it the most complex ops.
So in total, this game is amazingly light on the IBM BIOS services. In my estimation, porting it to BIOS-less 8080 system will only increase the size by 100 bytes at most.
The fun part of the 2600 is that it doesn't have any real graphics hardware. You produce the graphics scanline by scanline racing the beam. That's the main reason the graphics look the way they do, there's no memory for a frame buffer or even a single scanline unless you dedicate it yourself.
This is how you put an object on the screen on the Atari 2600 (VCS):
1) Horizontal positioning is done by sync. You have to write a value to a latch register in the exact moment, the beam crosses the desireed location. So the code has to engage in a delay loop of sorts. However, a CPU clock is 3 pixels long and a minimal delay loop is 5 CPU cycles, providing just a resolution of 15 pixels for this. Therefore, you have to work out a correction factor (+7 … -7 pixels) and write this to another register and trigger this by yet another write to a register.
2) Vertical positioning is done by counting raster lines (you have to do this anyway, since you have to trigger the vertical blanking and raster retrace on your own) and, if it's the right one, writing a non-null byte value to the sprite register in question. Of course, you have to clear it again for those lines where it ought not to show.
There are just two sprites and three single-pixel objects. So some repositioning on the fly and additional trickery is required to put something like Space Invaders on the screen. (There are also background graphics, consisting of 40 fat pixels, of which you can set up half of them, the other half either repeated or mirrored. Howewer, these fat pixels are 4 times a normal pixel wide and all of the same color and not much of use for displaying game characters.)
The TIA just produces a single raster line as set up over and over, resulting in a pattern of vertical stripes, which you'll have to interleave cleverly by your vertical display logic (called a kernel) manipulating the shape and color of things in order to display a meaningful image. However, as you're doing so, the beam is racing on…
Actually the 2600 has 128 colors, which is pretty insane comparing to later systems like the Commodore 64 and Spectrum, which only had 16 colors. (But you can only use 16 colors per line though, on the Atari.)