CS 1550 – Project 1: Graphics Library
Due: Sunday, September 21, 2014 by 11:59pm
Your instructor was learning ARM assembly language over break and was trying to make some projects for CS/COE 0447 to do. While text-based programs are okay, it’s really the graphical programs that make it a bit more interesting. So your instructor started to write a graphics library so the students could make a simple game.
In doing so, he noticed that a lot of the basic functionality the library provided was accessing the low-level operating system features that we talk about in 1550. The light bulb went off over his head, and project 1 was born.
In this project, you’ll be writing a small graphics library that can set a pixel to a particular color, draw some basic shapes, and read keypresses.
You will provide the following library functions (explained further below):
Library Call |
System Call(s) used |
void init_graphics() |
open, ioctl, mmap |
void exit_graphics() |
ioctl |
void clear_screen() |
write |
char getkey() |
select, read |
void sleep_ms(long ms) |
nanosleep |
void draw_pixel(int x, int y, color_t color) |
|
void draw_rect(int x1, int y1, int width, int height, color_t c) |
|
Each library function must be implemented using only the Linux syscalls. You may not use any C standard library functions in your library anywhere.
In this function, you should do any work necessary to initialize the graphics library. This will be at least these four things:
This is your function to undo whatever it is that needs to be cleaned up before the program exits. Many things will be cleaned up automatically if we forget, for instance files will be closed and memory can be unmapped. It’s always a good idea to do it yourself with close() and munmap() though.
What you’ll definitely need to do is to make an ioctl() to reenable key press echoing and buffering as described above.
We will use an ANSI escape code to clear the screen rather than blanking it by drawing a giant rectangle of black pixels. ANSI escape codes are a sequence of characters that are not meant to be displayed as text but rather interpreted as commands to the terminal. We can print the string “\033[2J” to tell the terminal to clear itself.
To make games, we probably want some sort of user input. We will use key press input and we can read a single character using the read() system call. However, read() is blocking and will cause our program to not draw unless the user has typed something. Instead, we want to know if there is a keypress at all, and if so, read it.
This can be done using the Linux non-blocking system call select().
We will use the system call nanosleep() to make our program sleep between frames of graphics being drawn. From its name you can guess that it has nanosecond precision, but we don’t need that level of granularity. We will instead sleep for a specified number of milliseconds and just multiply that by 1000000.
We do not need to worry about the call being interrupted and so the second parameter to nanosleep() can be NULL.
This is the main drawing code, where the work is actually done. We want to set the pixel at coordinate (x, y) to the specified color. You will use the given coordinates to scale the base address of the memory-mapped framebuffer using pointer arithmetic. The frame buffer will be stored in row-major order, meaning that the first row starts at offset 0 and then that is followed by the second row of pixels, and so on.
Using draw_pixel, make a rectangle with corners (x1, y1), (x1+width,y1), (x1+width,y1+height), (x1, y1+height).
Download the qemu-arm.zip file from the website and extract the files into a folder.
Double-click the start.bat file in the folder to launch QEMU.
Install QEMU through Homebrew. If you don’t have Homebrew, open a terminal and type:
ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
Go through the install steps. When done, install qemu by typing:
brew install qemu
That will install qemu. Now you can run start.sh in the zipped folder to launch qemu.
Using your appropriate package manager, install qemu-system-arm, likely part of your distro’s qemu package.
Then run start.sh in the zipped folder to launch qemu.
To keep downloads small, the disk image we have provided does not have a full development environment installed. To install gcc, gdb, and ssh/scp, run the script:
./devtools.sh
When this finishes downloading and installing, you should have the ability to use most basic Linux commands, nano for text editing, and gcc, gdb, and ssh/scp/sftp for transferring files. These commands will survive a reboot, so this only needs to be done once.
If you want to install other programs, you may use the Tiny Core Linux distribution’s package installer:
tce
This lets you search for a particular package or program name and install it.
After you’ve finished installing the tools, you may wish to make a backup of the disk image in case something happens and you don’t feel like redoing all of these steps.
Shutdown linux using the command (rebooting has been turned into poweroff by an option to QEMU):
sudo reboot
Then, make a copy of disk.qcow2 someplace safe. If things go wrong, you can always restore back to this point by replacing the disk.qcow2 file in this directory with the one you’ve backed up.
With the dev tools installed you can use scp (secure copy) to transfer files in and out of QEMU.
You can download the test driver program from thot with the command:
scp USERNAME@thot.cs.pitt.edu:/u/OSLab/original/square.c .
You can backup a file named library.c to your private folder with:
scp library.c USERNAME@thot.cs.pitt.edu:private
One of the major contributions the university provides for the AFS filesystem is nightly backups. However, the /u/OSLab/ partition is not part of AFS space. Thus, any files you modify under your personal directory in /u/OSLab/ are not backed up. If there is a catastrophic disk failure, all of your work will be irrecoverably lost. As such, it is my recommendation that you:
Backup all the files you change under /u/OSLab or QEMU to your ~/private/ directory frequently!
Loss of work not backed up is not grounds for an extension. YOU HAVE BEEN WARNED.
You need to submit:
Make a tar.gz file named USERNAME-project1.tar.gz
Copy it to ~jrmst106/submit/1550/ by the deadline for credit.