/* * square2.c * this program attempts to draw a square in a loop */ /* the width and height of the screen */ #define WIDTH 240 #define HEIGHT 160 /* these identifiers define different bit positions of the display control */ #define MODE4 0x0004 #define BG2 0x0400 /* this bit indicates whether to display the front or the back buffer * this allows us to refer to bit 4 of the display_control register */ #define SHOW_BACK 0x10; /* the display control pointer points to the gba graphics register */ volatile unsigned long* display_control = (volatile unsigned long*) 0x4000000; /* the address of the color palette used in graphics mode 4 */ volatile unsigned short* palette = (volatile unsigned short*) 0x5000000; /* pointers to the front and back buffers - the front buffer is the start * of the screen array and the back buffer is a pointer to the second half */ volatile unsigned short* front_buffer = (volatile unsigned short*) 0x6000000; volatile unsigned short* back_buffer = (volatile unsigned short*) 0x600A000; /* keep track of the next palette index */ int next_palette_index = 0; /* * function which adds a color to the palette and returns the * index to it */ unsigned char add_color(unsigned char r, unsigned char g, unsigned char b) { unsigned short color = b << 10; color += g << 5; color += r; /* add the color to the palette */ palette[next_palette_index] = color; /* increment the index */ next_palette_index++; /* return index of color just added */ return next_palette_index - 1; } /* a colored square */ struct square { unsigned short x, y, size; unsigned char color; }; /* put a pixel on the screen in mode 4 */ void put_pixel(volatile unsigned short* buffer, int row, int col, unsigned char color) { /* find the offset which is the regular offset divided by two */ unsigned short offset = (row * WIDTH + col) >> 1; /* read the existing pixel which is there */ unsigned short pixel = buffer[offset]; /* if it's an odd column */ if (col & 1) { /* put it in the left half of the short */ buffer[offset] = (color << 8) | (pixel & 0x00ff); } else { /* it's even, put it in the left half */ buffer[offset] = (pixel & 0xff00) | color; } } /* draw a square onto the screen */ void draw_square(volatile unsigned short* buffer, struct square* s) { unsigned short row, col; /* for each row of the square */ for (row = s->y; row < (s->y + s->size); row++) { /* loop through each column of the square */ for (col = s->x; col < (s->x + s->size); col++) { /* set the screen location to this color */ put_pixel(buffer, row, col, s->color); } } } /* clear the screen to black */ void clear_screen(volatile unsigned short* buffer, unsigned short color) { unsigned short row, col; /* set each pixel black */ for (row = 0; row < HEIGHT; row++) { for (col = 0; col < WIDTH; col++) { put_pixel(buffer, row, col, color); } } } /* this function takes a video buffer and returns to you the other one */ volatile unsigned short* flip_buffers(volatile unsigned short* buffer) { /* if the back buffer is up, return that */ if(buffer == front_buffer) { /* clear back buffer bit and return back buffer pointer */ *display_control &= ~SHOW_BACK; return back_buffer; } else { /* set back buffer bit and return front buffer */ *display_control |= SHOW_BACK; return front_buffer; } } /* the main function */ int main() { /* we set the mode to mode 4 with bg2 on */ *display_control = MODE4 | BG2; /* add black to the palette */ unsigned char black = add_color(0, 0, 0); /* make a green square */ struct square s = {10, 10, 15, add_color(0, 20, 2)}; /* the buffer we start with */ volatile unsigned short* buffer = back_buffer; /* loop forever */ while (1) { /* clear the screen */ clear_screen(buffer, black); /* draw the square */ draw_square(buffer, &s); /* swap the buffers */ buffer = flip_buffers(buffer); } }