All Source Code: Github
I was very interested in creating animations in assembly, so I chose to create an animated mario character for my MIPS project. Due to time constraints, I stopped there and didn't create an actual playable game, but this code could easily be refactored and continued to represent a super mario level.
Since I knew before starting that the codebase for this project would become progressively messier and more difficult to debug, I decided to create macros for most small-but-annoying tasks in order to make later development more painless. This included single line drop-in replacements for
I also had compound macros that invoked other macros, such as:
You can find a flowchart of the most high-level macros and how they're used in the flowchart diagram below.
Using macros was a critical part of development since it made debugging code significantly easier.
Now let's do a high-level walkthrough of the codebase and talk about some important design decisions.
I wrote python code (which is also supplied in this submission) that was used to convert the following 2 gifs of
mario running and idling (standing) into individual frames, then process those into lines of code in MIPS that use
my draw_pixel macro.
This gave thousands of commands using the macro
draw_pixel_with_color_and_offset_immediate(x, y, color)
draw_pixel_with_color_and_offset_immediate(24, 0, 0x007D2F3A)
Here's some of the higher-level labels
Sample run: https://youtu.be/LhNIEds_Tz0
The code for animations consists of over 25,000 lines of calls to the draw_pixel macro with different coordinate and color arguments. This is obviously not the best way to do animations - a far more efficient way that I tried was converting the frame data into a different file format, then loading that into MIPS memory, but I kept running into memory errors so I ditched the approach for the easier way of just writing out all the function calls for every pixel for each frame.
Currently, when mario exits the screen, there is no code that puts his x position on the other side of the screen - instead what happens is that the x value is incremented beyond the max x value, so the y value effectively increases by 1 in the code that finds the memory address for the reference pixel.
The x velocity is dampened by 1% each frame if the player is on the ground, simulating friction, but this restriction does not apply when the player is in the air. Thus, it is possible to achieve infinite speed by repeatedly jumping and moving in one direction, since the screen wraps the player around whenever mario exits leaves the viewable area. This could be prevented by enforcing a maximum X velocity for ther player.
You can click/drag/zoom on the below interactive flowchart, or open in another page using the link below
Flowchart External Link