Note: I wrote a post a while ago detailing a hackfix for the threading issue mentionned below. You can find it here.
MIPS is a RISC (reduced instruction set computer) architecture used in CPUs such as the 32-bit MIPS Allegrex R4000 found in Sony’s PlayStation Portable. Throughout the first semester of Console Development 1, year 2 of my BScH in Computer Games Programming, we worked on simple applications using MIPS assembly language. Personally, I find programming in assembly language very relaxing when compared to regular programming, and I hope one day to find the time to look into 6502 assembly as a step towards a long-standing dream.
Following is the description of my main two achievements to date using MIPS: Snake, and PrimLib.
Download: Assembly | Video
A few days after being introduced to the MARS MIPS simulator I dropped on the Bitmap Display and Keyboard and Display Simulator tools included with it. Being primarily a games programmer, the first thought that occurred to me was ‘I can use this’. Move ahead a few hours and I had the basis of a working snake game written in assembly. Another few days and a recode later the game was near complete, but there was one error that reared its head, wherein the entire MARS simulator would randomly crash while running my program.
As it turns out, the fault wasn’t in my code, but in a threading issue with the Keyboard and Display Simulator. An hour or so of poking around in the java source provided with MARS enabled me and my friend to make a quick fix to stop the lock-up from occurring, and I sent a quick email off to KenVollmar@missouristate.edu about the issue.
With the hack-fix in place, my Snake game was complete. However, while I will provide the assembly for the game I won’t distribute the modified version of MARS needed to run it soundly, so it won’t run for long unless you care to fix that yourself.
How Snake Works
The main issue I ran into when programming snake in MIPS was how to store data about all the entities. At some point I discovered that the two alpha bytes in the colours used for the display were simply being wasted, so I opted to store only the colour data for the display, the address of the head and tail of the snake elsewhere, and store all other information in the alpha bytes using different numbers for different meanings. As the snake moves around a new head segment is placed at the front, and the old head position is replaced with a block of the same colour, but with a code in the alpha bytes indicating the direction of the new head. When that segment is at the address in the tail register the direction stored is recovered and used to swap the address in the tail register to the next segment along. The old segment is then replaced with the background colour so that the snake’s tail follows its path. Information on food and walls is also stored in the alpha bytes, and this system could potentially be used to identify an even larger number of entities, or even combine separate flags using bitwise operations.
PrimLib was written for the first Console Development 1 assignment. It’s a collection of functions which draw primitives to the Bitmap Display included in MARS. The assignment was marked for efficiency, and the algorithms implemented. Out of personal preference I chose to prioritize reliability at the sacrifice of some performance by ensuring that all of my functions performed boundary checks and clipping where necessary. Going out of bounds in the Bitmap Display tool doesn’t usually crash MARS, but it does wrap around and produce undesirable results.
Most of the algorithms are fairly easy to implement and/or are based on existing algorithms such as the Bresenham’s Line Drawing and Cohen-Sutherland Line Clipping algorithms. You may think it odd, but I actually implemented some algorithms, such as Bresenham’s and Cohen-Sutherland Line Clipping in MIPS before implementing them in C++ for the Introduction to 3D Graphics Programming module, in which I wrote a software renderer that required several similar functions. The screenshot seen above is running the test data I implemented to stress test all of the algorithms implemented. What remains then is to list the functionality of PrimLib:
setpixel(int x, int y, int colour)
drawline(int x1, int y1, int x2, int y2, int colour)
drawrectangle(int x, int y, int width, int height, int colour)
drawfilledrectangle(int x, int y, int width, int height, int colour)
drawpolygon(point points, int count, int colour)
drawcircle(int x, int y, int radius, int colour)
drawfilledcircle(int x, int y, int radius, int colour)
clipline(int x1, int y1, int x2, int y2)