The goal of this assignment is to make a C program that will run on a Game Boy Advance emulator. Your program will be an interactive graphical application. Your program can be a game, or any other interactive program that meets the requirements outlined below.
While completing this program, you will learn about low level hardware programming in C. This program is similar to how you would write device drivers or parts of an operating system, which are typically written in C. The GBA devices (screen, buttons, DMA controller, etc.) are accessed via memory-mapped I/O. You will access specific hard-coded memory addresses in your C code. You will gain experience with bit masks and bitwise operators to set bits in the device registers. The GBA is also a very slow computer. You will learn tricks to optimize the performance on a resourcelimited hardware device (such as DMA, integer math instead of floating point, and so forth).
You will write an interactive graphical application in C that runs on the GBA emulator. This application can be a game, or any application that meets the feature and technical requirements below. For ideas on what you could do, please see What to Make in the Appendix. This is an open-ended assignment. Just be sure that your program meets all the requirements. We have provided some resources to help you get started. You can use the outline structure of a program, and fill in code to do what your application specifically does. You should have at least one .h header file and one .c file. You can have more if you wish. Your program must use DMA, waitForVblank(), and Mode 3 video. You must have a title screen, in addition to the other screen(s) in your program. You must use button input and include some text on the screen, as well as other images (a background image, and small image, e.g. a character that can move up, down, left, and right). You must detect collisions between two objects on the screen. You must not have any tearing (visual distortion, due to drawing too many things in each screen frame on a slow computer). Please see the full list of requirements below.
You will be evaluated on meeting all the feature requirements and technical requirements described below. This assignment offers an opportunity for you to be creative if you want to. However, creativity (and artistic ability) are NOT required. Your grade will be based on meeting all the requirements outlined below. If you write a very creative program, but do not meet all the requirements, you will lose points. On the other hand, if you write a minimal program that works and meets all the requirements, but is not exciting, you will get full credit. Please do not feel pressure to be creative if that is not your personality, or if you do not have time to do so.
2 Before You Start
To tackle this homework, we’ve provided:
• A gba.h file that contains all of the necessary GBA declarations such as DMA, videoBuffer, etc. • Several other files which contain more “starter” code to get you rolling. See Section 5.2 for details. • A Makefile that you can use to compile and run your program by typing or make mgba from the docker terminal. Note: since there are graphics involved with this assignment, the integrated terminal will not be able to display your project. Make sure to use docker through your browser to view the GBA.
In addition, here are some other helpful resources: • Lab Guides/Slides • Lecture Slides 17 and 18 • TONC - full documentation of the GBA, including advanced features • Lecture Code: Canvas > Files > Source Code > gba • The Appendix, including GBA Coding Guidelines
Feel free to use code from class resources as you need to, but as always, not from your friends or random sketchy Internet sites.
Your main.c should be something different from lecture code, since in this homework you will be creating your own program. You should keep the core setup with videoBuffer, MODE 3, waitForVBlank, etc., though.
Additionally, please do not rehash lecture code in your program; programs that are merely slightly modified lecture code are subject to heavy penalties. You may borrow some idea and structure from lecture code, but your code should be your own, and your idea should be distinct from lecture code in some way. For example, you are allowed to create games or programs that include bouncing squares, like Pong; however, you should attempt to add new features, like drawing an image instead of a square, or making the square change velocity whenever it bounces. If you have concerns over whether or not your idea is different enough from the s in lecture, feel free to ask a TA in office hours or on Ed Discussion.
2.2 Words of Warning
• Do not use floats or doubles in your code. Doing so will slow your code down greatly. The ARM7 processor the GBA uses does not have a floating-point unit which means floating point operations are slow as they are done in software, not hardware. Anywhere you use floats, gcc has to insert assembly code to convert integers to that format. If you do need such things that you think requires floats or doubles, you should look into fixed point math. • We strongly recommend that you do not use malloc() in your program. Instead, use arrays large enough to hold all possible elements (images, game characters, etc.) that you could possibly have at one time. You can use an array of structs, as in the lecture code example. • Only call waitForVBlank once per iteration of your main loop. Each waitForVBlank call will stall your program for about one sixtieth of a second, so excessive calls will make your program feel slower. • Keep your code efficient; particularly, try to do as little drawing per frame as possible. See the guide on Reducing Tearing for tips on how to make your drawing more efficient. • If your program does have tearing, keep in mind that it will affect the top of the screen first. So, if text or images drawn at the top of the screen are disappearing for some unknown reason, it is likely that your program is attempting to draw during the VDraw period, which is often leads to tearing. • If you choose to use more advanced GBA features like sprites or sound, making them work is your responsibility; we (the TAs) do not really know how they work, so we sadly can’t help you. (TONC is useful to reference when implementing these features, if you do choose to add them.) Note that sound support is currently unstable and is unlikely to work in the current version of the Docker container.
The autograder for this assignment only checks that your code compiles, so the rest of your grade entirely depends on the following requirements. Note: the following point values may be changed, but we will not add more requirements or make requirements more strict.
3.1 Feature Requirements
• Your program must compile. This is the most important requirement, since we can’t grade your feature requirements otherwise. (1 point) Note: it is an automatic “0” if your program does not compile. • You must use 3 distinct images in your program, all drawn with DMA. (10 points) – Two full screened images sized 240x160. One of these images should be the first screen displayed when launching your program. – A third image which will be used during the course of your program. The width of this image must be less than 240 pixels and the height of this image must be less than 160 pixels. – Note: all images should be included in your submission. – You should use nin10kit (as mentioned in section 5.2.2) to convert images in standard formats like PNG and JPEG into C header files with a constant short array containing 16-bit pixel values. See the Images section in the appendix for instructions on how to create your own custom images. • You must be able to reset the program to the title screen AT ANY TIME using the “select” (backspace) key. This resets the ENTIRE program, including application state. (10 points) • Button input should visibly and clearly affect the flow of the program. Examples include pressing the start button or enter key to transition from a game’s title screen into gameplay, or using the arrow keys to move an image across the screen. (10 points) • You must have 2-dimensional movement of at least one entity (an entity that moves both left/right and up/down). One entity moving up/down and another moving left/right alone does not count. (10 points) • You should implement some form of object collision. Think of detecting collisions as determining if two on-screen items are overlapping. For example, if your player overlaps with a rectangle on the screen, then that is an example of a collision. Please make your collision more intricate than an object colliding with the borders of the screen; try to implement collision between objects. For programs where application of this rule is more of a gray area (like Minesweeper), core functionality can take the place of this criteria, such as the numbers for Minesweeper tiles calculated correctly, accurate control, etc. When in doubt, ask a TA for clarification. (10 points) • Use text to show progression in your program. (10 points) – Examples of text progression include on-screen timers, score counters, or any other text that displays useful information to the user. – Several functions for drawing strings are already implemented in gba.h and gba.c. To use these, you must implement drawPixel in gba.c. – You may find the snprintf function to be useful when displaying numerical values. This function works like printf, except it fills a character array instead of printing to console. – See the lecture code for an example of how to implement text progression. – If you choose to implement a timer, think about how you can keep track of time. (Hint: the GBA runs at 60 ZFPS, so how can you turn the vBlankCounter into “time elapsed”?) • There must be no tearing in your program. Make your code as efficient as possible! Check out the appendix for tips on how to reduce tearing. (18 points)
3.2 Technical Requirements
• Include a README.txt or README.md file with your submission that briefly explains the program and the controls. Don’t forget to put this in your Gradescope submission! (2 points) • Your program must be in Mode 3! – Mode 3 should be the very first thing set in the main method. (No added points, but this is pretty much required for some of the other requirements.) • You must also implement drawImage with DMA. The prototype and explanation are later in the assignment. Depending on when you are reading this, DMA may not have been covered in lecture yet. If this is the case, you should implement this function with setPixel first, and reimplement it with DMA once it’s been covered in lecture. (6 points) • You must implement waitforVBlank() (4 points) • You must use at least one struct. The struct must be defined in a header (.h) file, not a source (.c) file. If your program has an object that moves around the screen, you may find it useful to create a struct that stores the object’s position. (5 points) • You can create your own header file or use the main.h header already available. You must move any #defines, function prototypes, and typedefs to this file from your code, along with your extern videoBuffer statement if you wish to use videoBuffer in other files. Remember that function and variable definitions should not go in header files, just prototypes, extern variable declarations, and struct declarations. (4 points) – As always, do not include .c files into other files. Only .h files should be included and .h files should contain no functional code. – It is optional for you to use other .c/.h files to organize your logic if you wish. Just make sure you include them in your submission and Makefile.
Please archive all of your source code files as a zip or a tar and upload to Gradescope under the “Homework 8” assignment. This includes all .c and .h files needed for your program to compile and run. Do not submit any compiled files. You can use make clean to remove any compiled files, or make submit to remove compiled files and create a tar archive. This tar archive should also contain your README.
5.1 Appendix A: What to Make?
You may either create your own interactive graphical application the way you wish it to be as long as it fulfills the requirements, or you can make applications that have been made before using your own code. However, your assignment must be yours entirely and not based on anyone else’s code. This also means that you are not allowed to base your program off the code posted from lecture. Programs that are merely slightly modified lecture code are subject to heavy penalties. You may borrow some ideas and structure from lecture code, but you should write your own code, and your application should be distinct in some major way. If you have concerns about whether or not your idea is different enough from lecture code or if your idea would satisfy requirements, feel free to ask a TA. Below are some previous programs that you can create or use as inspiration:
5.1.1 Example Programs
Minimum Viable Product: • As stated in the Overview, you do not need to make a complex or creative program; it must only fulfill the minimum requirements • Create a start screen and a win screen that use the two required full-screen DMA images • Use the arrow keys to move a small DMA image around the screen; store this image’s position using a struct • Transition to the win screen when the player-controlled image touches a goal zone (represented via a colored rectangle or image) • Use text to show an on-screen timer, and display the total time taken on the win screen Interactive Storybook: • Recreate a story from a movie or a book using the GBA • Use text to narrate what is currently happening in the scene • Use the controls to advance to the next scene or control a character within the scene • Smooth movement (for any moving characters or objects) • Start off with a full screen title image and end with a full screen credits image • Characters represented by structs Galaga: • Use text to show lives • Game ends when all lives are lost. Level ends when all aliens are gone. • Different types of aliens: there should be one type of alien that rushes towards the ship and attacks it • Smooth movement (aliens and player) • Aliens and the ship represented by structs
The World’s Hardest Game:
• Smooth motion for enemies and player (no jumping around) • Confined to the boundaries of the level • Enemies moving at different speeds and in different directions • Sensible, repeating patterns of enemy motion • Enemies and the player represented by structs Flyswatter: • Images of flies moving smoothly across the screen • Player controlled flyswatter to swat the flies • Score counter to keep track of how many flies have been swatted • Fullscreen image for title screen and game background • Enemies and the player represented by structs Text Editor: • Pick some sample pre-rendered text, and display it in a window on the screen. • Use the up/down/left/right buttons to move a cursor through the text. (Display the cursor somehow. Advanced: use time to make it blink over the current position.) • Pick another button to be the mouse down button. When the mouse is down, the arrow keys will select the text you mouse over. (Highlight the selected text. Perhaps reverse foreground and background colors.) • Choose three more buttons to be cut (ctrl-X), copy (ctrl-C), and paste (ctrl-V). Paste will insert text (from your clipboard) at the current cursor position. • Collision detection (feature requirement) involves determining which character the cursor is pointed at. • Find a way to include the three required images. Color Picker: • There are 32,768 unique colors on the GBA. Draw a two-dimensional color palette rectangle, including all the possible colors. • Use the arrow keys as a mouse to move a crosshairs cursor around the color palette. • Choose a key to select a color. Display that color in a solid box somewhere else on the screen. • Optionally choose a separate background color, and display that. (Find a way to choose if you are selecting foreground or background color.) • Collision detection - which color am I currently pointing the mouse at? • Find a way to implement the three required images. • Variation (or extension of this): Implement part of Microsoft Paint - a simple drawing program. Use the arrow keys as a cursor. Use another key to select draw or erase (or other tools).