GLIM - Graphics Library for MIPS

Created for the University of Alberta CMPUT 229 Computer Architecture course

Author: Austin Crapo, June 2017


Information

GLIM is a collection of sub-routines to emulate graphics and it is meant for use with SPIM and the XFCE Terminal Emulator. Although most UNIX-system terminals will work, the XFCE was the only used for testing during development. The true requirement is that the terminal emulator be DEC VT220 compliant. It the terminal emulator is not compliant GLIM functions will produce a bunch of garbled text. The purpose of GLIM is to abstract away the terminal escape sequences into an organized library that allows beginner assembly programmers to include visual elements in their work. Some high-level functions are presented here. Refer to GLIM's documentation to get the indivudual function requirements for usage. The library is also available for RISC-V.

Access to the Code

The source code for GLIM can be found at: https://github.com/cmput229/GLIM

License

GLIM is free to use, available under the MIT license. Atribution under this license is not required, but always appreciated.

Usage

Starting GLIM

Before you call any of the GLIM printing routines you must call the following routine:

jal    startGLIM

This helper function resizes the screen (see input arguments), hides the cursor (which otherwise will interfere with printing), and clears it all to the default background color.

When your program finishes, and if had started GLIM, then call the following:

jal    endGLIM

endGLIM undoes most changes so that the terminal window is not left unusable when your program exits. Unfortunately endGLIM cannot resize the window back to it's original size because at the moment there is no method to read and store the terminal size at the start of the program.

Conceptual Architecture

The main device in GLIM is the terminal window which contains a certain number of rows and columns. These are referred to throughout the documentation as rows and cols or (r, c).

If you stare at the space between the boxes long enough you'll probably see an optical illusion

The tuple describing a position on the grid is (r, c) and not (c, r). Remember this. Terminals were designed to print text top to bottom, left to right. Their underlying control structures are built on this assumption. Thus the row number comes before the column number. The origin (0, 0) is at the top left of the terminal window:

If you think this is confusing, imagine the confusion trying to program the library while transforming coords each time, the overhead would be awful and the bugs many.

The screen above is a square grid, but terminals and fonts are not square (even if they are monospace), thus a square grid renders a rectangular shape.

Screen Updates

The terminal display that you access with GLIM should be treated as a write-only persistant array. Thus, you can 'push' updates to the screen, but you cannot revert them, you cannot see if they were successful, and you cannot make decisions based on the screen state. Instead, the best method to use GLIM is to keep your own data structure representing the screen, then when a change needs to be made to that data structure, you can make a corresponding change in the screen by 'pushing' updates to it.

There are two main ways to handle the synchronization between your own data structure and GLIM. Depending on what you are trying to accomplish one will be preferable over the other, but the second is much better practice and more versatile.

Method 1 - Clear and Refresh

This is the brute force method. Each time any updates need to happen, you clear the entire screen (using clearScreen). Then you iterate over your data structure and use printString to print each element of the display again.

Drawbacks: less built-in function color support, if you need to reprint too often or have too many elements that need printing your screen will flicker uncomfortably. This is because clearing the terminal is very slow (it only requires one command), but printing requires that about 20 characters be printed for for each tile you need to print on the screen. A monitor however refreshes very fast. So your monitor is likely to refresh at least once after you have cleared, but before you are done printing all the elements, causing the flicker.

Advantage: quick to setup for testing purposes so you can focus on getting the underlying code working.

Resources: see the clearScreen and printString methods.

Method 2 - Batch and Release

This method focuses on calculating changes that need to be made to the screen, and then printing them. When your underlying data-structure representing the screen is changed, you add the changes to a list. When you have enough changes, or when you are finished calculations or ready to print, you then print all the updates at once, leaving the unchanged portions of the screen untouched. This can be important for things such as games or art, where you would rather have all the updates show at once or with as little delay between them as possible. There is a slight overhead in keeping track of this list, however, not nearly as much as clearing the whole screen and reprinting. Also, terminals themselves are slow to print so there's generally no way you can completely eliminate delay between the start and end of printing, but you can reduce it. GLIM has an included method to assist with this concept for printing, that rolls together color printing in a simple 'batch job' format.

Advantages: less overhead, fewer updates, more built-in color support, potentially smoother animations

Resources: see the batchPrint method.

Of course, there are other methods that can be designed using the individual functions and smart programming. Feel free to experiment. A hybrid approach might for example use printString and setColor to achieve color printing and carefully be programmed to avoid reprinting to many tiles. It is left up to you how you use this library.

Color

Support for colors in terminals has been around for a long time - but universal adoption is not yet a reality. For those terminals that do support it, different levels and standards have been adopted as the terminal emulators matured. Seven color terminals were upgraded to 256 color terminals and then to a 3-byte Red-Green-Blue (RGB) color generation. GLIM is designed to support 256-color terminals or above (3-byte RGB terminals will also work because they also support the 256-color codes). The xfce4-terminal is a 256-color terminal. Below is a table that shows the supported color codes (see setColor or batchPrint for usage).

In GLIM you change terminal color settings (using setColor) in the same way that you print to the terminal. You may 'push' a color setting, but you cannot check what the current setting is. Future prints will be in the color set, past prints will not be affected. Therefore, part of startGLIM is to set the color to the defaults (default is based on your terminal defaults, which are usually white text on black background in Linux). The restoreDefaults method can be used to restore the default color settings.

The following table is extracted from wikipedia
[hide]256-color mode — foreground: ESC[38;5;#m   background: ESC[48;5;#m
Standard colors High-intensity colors
 0   1   2   3   4   5   6   7   8   9  10 11 12 13 14 15
216 colors
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
Grayscale colors
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

Additional Notes

The purpose of GLIM is to abstract out the escape codes that move the cursor and change printing styles into a workable graphics package. Some terminal emulators allow more advanced capabilities that are not currently implemented in GLIM. Your terminal emulators' escape-code documentation contains information about such capabilities. If you create new functions, please send your code to crapo@ualberta.ca with enough author info so I can cite you and I'll consider adding it to the library. A hint for those wanting to create animations or more pretty graphics - there is no character that can be printed that covers an entire grid space in most default fonts. The unicode 'full block' character makes for a great pixel element in most printing cases but leaves a sliver of space above and below but not side to side. If you find a square font where the full block covers, please let me know and I will look into including support for it in GLIM. A hacky method is to set the color of the background and print a space (" ") but this can effect clearScreen because it will set the entire screen to the current background color.