Please download the newest MARS, MARS_2191_c.jar, from the software page.

In this lab, you’ll start using the Keypad and LED Display Simulator plugin to draw some sweet low-res graphics!

Make a file named abc123_lab6.asm in a new directory.

Opening the plugin

In MARS, go to to Tools > Keypad and LED Display Simulator. Not Keyboard and Display MMIO Simulator.

This will pop up a window. Click the “Connect to MIPS” button in the bottom left.

Once it’s connected, you don’t have to close the window or reconnect it.

You can re-assemble and re-run your program as many times as you want while the display is open.

Using the plugin from your code

.include "led_keypad.asm"

Now you can use the constants and call the functions from led_keypad.asm!


Okay the lab for real now

For your second project, you’ll make an interactive video game. Today’s lab has all the same parts as a game, but very simplified. It will look something like the thing on the right when you’re done.

The way any interactive program works is like this:

  1. wait for a little while
  2. check for user inputs
  3. respond to those inputs by updating your program state
    • “state” means “your variables, data structures, etc.”
  4. change the output (screen) to reflect the new state
  5. loop back to step 1

You had a similar program flow in project 1: user’s turn, get inputs, dealer’s turn, update variables, loop again. The difference is… it’s faster. The player and opponent(s) get 60 turns every second! AAAAAH!


1. First steps

Making your state variables

Making the main loop

The best place for the main loop is - you guessed it - in main.

Waiting a little while

This is important. Without it, your program will run WAY too fast and you might not be able to stop it without force-closing MARS.

Syscall 32 lets you pause your program for a bit. It takes the number of milliseconds to wait in a0. There are 1000 milliseconds in one second. You want this loop to run 60 times per second. So how many milliseconds do you have to wait? Do this syscall as the first thing inside your main loop.

If MARS stops responding when you assemble your program, you didn’t download the newest version of MARS.


2. Drawing the dot on the screen

The screen is a 64 x 64 pixel display. Each pixel is a colored square that can be one of eight colors: black, red, orange, yellow, green, blue, magenta, or white. The led_keypad.asm file gives you many functions for drawing things onto the screen. The one you’re about to use sets one pixel to a color.

It should do the equivalent of this code:

display_set_pixel(dot_x, dot_y, COLOR_WHATEVER);

Now if you run it, you should see….. nothing!!! What???


3. Making your drawings appear

Like this.

In your main loop, after calling draw_dot, call display_update_and_clear. NOW your dot will appear.

What’s going on?

The display plugin is double-buffered. When you draw to the screen, you are really drawing to a hidden area in memory first. Then you must call a function to actually show the graphics on the screen. This technique avoids problems when the screen is redrawn while you’re in the middle of drawing things, causing weird graphical artifacts.

You should only call display_update_and_clear ONCE per main loop iteration, after drawing everything.


4. Moving it around

The way input works in this plugin is that you use the arrow keys and B key on your keyboard. Then, your program can detect that by using input_get_keys, another function from led_keypad.asm. It returns which keys are being held down, but it does so by returning bitflags.

Bitflags

A special case of bitfields is when all the fields are 1 bit long. In that way, we can think of an integer as a small array of boolean values. We call this bitflags.

input_get_keys returns an integer where the lower 5 bits represent the four arrow keys and the 🅱️ key.

OK, tangent over

Here’s pseudocode for what your check_for_input function should do. This is not an if-else if-else if… This is a sequence of 4 separate ifs.

You might be wondering why we decrease the Y coordinate when pressing up. It’s because the origin (0,0) is at the top-left of the screen, and the Y axis increases downwards.

v0 = input_get_keys()

if((v0 & KEY_L) != 0) // bitwise AND!
    dot_x--;
if((v0 & KEY_R) != 0) // KEY_L, KEY_R etc. are constants.
    dot_x++;
if((v0 & KEY_U) != 0) // use the constant names.
    dot_y--;
if((v0 & KEY_D) != 0) // don't hardcode the values.
    dot_y++;

Now run your program, click the display, and use the arrow keys on your keyboard. It should work, but… try going off the top or bottom of the screen. What happens?


5. Moving it around, without crashing

What’s happening is your x and y coordinates are going negative or off the sides of the screen. On the top side, you’re going to start writing into a part of memory you’re not allowed to, so it crashes.

To prevent this, you have to limit the x and y coordinates.

At the end of your check_for_input function, before it returns, do the equivalent of the following:

dot_x = dot_x & 63; // bitwise AND!
dot_y = dot_y & 63;

Remember what this does? We learned about this as a shortcut for another mathematical operation…

Now your dot should wrap around to the other side like in the gif at the top of this page.


Fun things to try


Submitting

Do not submit led_keypad.asm. Just your lab file, thanks.

Make sure your file is named username_lab6.asm, like jfb42_lab6.asm.

Submit here.

Drag your asm file into your browser to upload. If you can see your file, you uploaded it correctly!

You can also re-upload if you made a mistake and need to fix it.