Created for the University of Alberta CMPUT 229 Computer Architecture course
Author: Austin Crapo, June 2017
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.
The source code for GLIM can be found at: https://github.com/cmput229/GLIM
GLIM is free to use, available under the MIT license. Atribution under this license is not required, but always appreciated.
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.
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).
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:
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.
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.
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.
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.
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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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.