BIOSnake
- 5 Devlogs
- 19 Total hours
Snake without an operating system, in 16 bit real mode, in x86 assembly!
Snake without an operating system, in 16 bit real mode, in x86 assembly!
The snake now has some food that appears on the screen. Not much to say here about the feature, it’s snake! But the implementation is a little bit more interesting. In computers, random numbers aren’t much of a thing, so you’ll usually have to settle for pseudo random numbers, but, CPUs today have an RDRAND instruction for generating random numbers from thermal noise and whatnot inside the CPU. but even though it’s on practically every chip today, I still opted not to use it, because
And we want this snake to be able to run on the original i386, don’t we?
So instead I decided to use a simple pseudo random number generator I just whipped up on the spot by multiply the seed by some big numbers and xor’ing it with itself a couple times. it’s definitely not cryptographically secure, but it’s snake, so whatever.
Now that the game is done, I’m gonna add a couple more features just so the game is a bit more more comfortable to play. I plan on adding:
Sadly there’s no apple yet so the snake is getting pretty hungry.
I made the snake finally able to get longer than 1 segment through a circular style array for keeping track of the head. This means that there is an array for all the segments that store the X and Y, and the head slithers through the array overwriting the tail segment so that you don’t need to copy the whole array forward every time the snake moves.
With this way of implementing the snake, you need to shift forward all the segments in front of the snake’s head in memory so that it creates a free space in front of the head, and so the head can move into the free space instead of overwriting the tail.
It’s a pretty simple concept, but I had a lot of trouble enacting this in assembly. Having to think about individual bytes isn’t something I’m used to from having data types handled automatically by higher level languages like C.
As I was writing more assembly, I noticed a moment when whenever I added any more instructions, the screen would just go black. I knew I might be scooching up to the 512 byte limit, so I ndisasm’d the binary and found out that, sure enough, I only had 2 more bytes left!
I was preparing to have use more than 512 bytes for my program, so I knew roughly what I needed to do.
You just need one bios interrupt to read a couple sectors (512 byte chunks) into memory, and moved some code around, and now I have practically unlimited (a couple thousand bytes) to work with!
I drew a grid for the snake to move on.
The code for the nested loop is not readable at all, but then again, it’s in assembly, no matter how you write it it’s unreadable.
I had an issue with the rectangle size being 0, because the size is passed to the drawing function through the DX register and I forgot that the MUL instruction doesn’t just store the result in AX, but also the DX register. This part sounds a bit weird but the stardance devlog guide says to “Include the friction”
I know these devlogs may seem uneventful or dull, but writing anything in assembly is a hard task. It took me over an hour to draw a grid!
This is my first devlog of making (or at least trying to make) snake without an operating system using BIOS interrupts and 16 bit x86 real mode assembly.
I’ve made my functions for clearing the screen and drawing a rectangle, and it only took 5 hours to do! A lot of was also researching calling conventions, which registers can do what, and wondering why you can’t access memory with the stack pointer register (???? why cant you it LITERALLY has the word pointer in its name)