gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > help with macro taking user input(gba)

#145556 - speedemon35 - Sun Nov 18, 2007 1:05 am

Hello all. Name is Daniel and i'm currently studying computer games technology. As the name implies at some point in the near future i'll be programming games. I'm in first year and sadly i need help with programming the gba. I'm using dev kit pro if that will make any difference btw. A few things you should know before hand: My current games technology teacher is possibly the last person you'll ever want to meet or have teaching you. Only support he ever gives is the word google so that will probably explain why i don't have a clue on what to actually look for in the gba tutorials.

Anyway i'm hoping someone here can give me some serious help as i've been trying to figure this out for a full week and i still can't get any of it right:
The tasks i was was set seem simple enough:


1. Write a function or macro, which takes three values between 0 and 31, and converts this to BGR 16 bit format. For example, the function prototype should look like u16 BGR(u16 b, u16 g, u16 r);
^ my actual problem^

2. Draw a yellow pixel in the centre of the screen (in mode3).
^done this one as it was just a guessing numbers game^

3. Allow the pixel to be moved around using the D-Pad (make sure it doesn?t go past the boundaries of the screen). (guessing something like offset limit will do the trick here)


4. Change pixel colour using A and B buttons.
^no clue about that either as i haven't even looked at any possible tutorial on how to do it^

anyway here is the code:


Code:

//================
//    HEADERS
//================
#include "gba.h"

//================
//   CONSTANTS
//================

#define BG2_ENABLE      0x400   
#define MODE3         0x3
#define FRONTBUFFER      (u16*)0x6000000

#define RGB(r,g,b) ((b<<10)+(g<<5)+r) //u16 --> unsigned short, this is macro for RGB() 15bit color format
#define ScreenWidth 240
#define ScreenHeight 160

//================
//    GLOBALS
//================
u16* g_uspVideoBuffer   = FRONTBUFFER; //This is were we are currently drawing

//================
//   FUNCTIONS
//================

//================
//   Function: PlotPixel16(int, int, unsigned short int)
//      Notes: Plots a pixel in the specified colour
//       Date: 14/2/2002
//================
void PlotPixel16(int in_iX,int in_iY, unsigned short int in_usColour)
{
   g_uspVideoBuffer[(in_iY) * ScreenWidth + (in_iX)] = (in_usColour);
}


//================
//   Function: main()
//      Notes: Main entry point into rom
//       Date: 14/2/2002
//================
int main()
{

   //REG_DISPCNT (defined in gba.h) is the main display register that controls
   //the mode of operation which backgrounds are enabled and which buffer is
   //currently being drawn by the GPU.
   //this sets the screen mode to mode three and enables background 2
   //background 2 is required for all bitmap modes(3-5)
   REG_DISPCNT = MODE3 | BG2_ENABLE;
   
   unsigned short yellow  = RGB(31,31,15);
   //unsigned short green= RGB(0,31,0);
   //unsigned short blue = RGB(0,0,31);
   //unsigned short white= RGB(31,31,31);
   
   
   //draw a pixel on GBA screen
   PlotPixel16(120,80,yellow);
   //PlotPixel16(130,70,green);
   //PlotPixel16(110,90,blue);
   //PlotPixel16(130,90,white);
   
   
   while(1){}

   return 0;

}



the actual macro is here:
Code:
#define RGB(r,g,b) ((b<<10)+(g<<5)+r)

and i'm supposed to edit it inside the code so that it does what task 1 asks

Write a function or macro, which takes three values between 0 and 31, and converts this to BGR 16 bit format.

As you might have guessed by now i honestly don't have the smallest clue on how to properly edit the code without messing things up.
That entire thing was programmed in C, and the closest thing i know to c is C++. But between C++, C, and actual gba programming there are quite fine differences.

I know how to do what the task asks me in C++ as its just a simple matter of defining the macro, passing parameters with a cin user input in the middle. I wasn't quite able to do the same thing in C since parameters are handled a bit differently in C and i couldn't quite get the cout and cin part in C either since i don't know what the reserved keywords are for it.

With all that i still did try to edit the code to make it work on the gba but I'm never able to do anything correctly. NO matter what i write i keep on getting error not in scope of function regardless of where I put it in. I tried declaring my stuff globally but even then it complained about not in scope of function and just said ERROR 1 and fails to load the gba correctly.

I'm terribly sorry for wasting your time as this must sound pretty pathetic and its probably something basic for all of you but i simply got stuck with the worst possible imbecile for a teacher who is unable to provide any actual support what so ever.


Thank you for your time,
Sincerely
Daniel

#145557 - tepples - Sun Nov 18, 2007 1:22 am

The C equivalents of cout and cin are stdout and stdin, respectively. But as far as I can tell, the Game Boy Advance system has no useful counterpart to cin or stdin, in part because consoleInit() of libgba does not install an on-screen keyboard or any other stdin handler.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#145579 - speedemon35 - Sun Nov 18, 2007 1:10 pm

Oh well so much for ever getting this junk to work. Thanks for your help though

#145638 - ScottLininger - Mon Nov 19, 2007 7:41 pm

Hello, Daniel! Welcome to the forums.

speedemon35 wrote:
Oh well so much for ever getting this junk to work. Thanks for your help though


Whoa, don't give up so easily. Trying to understand a macro when you're still trying to grasp the programming basics isn't the best place to start. I'd begin with problem #3.

You already have a function that is successfully drawing a pixel, right? So don't worry about the color macro just yet. Let's start with getting some user input from the GBA and making your pixel move.

Step 1: Create some variables for the current pixel position:

Do you understand the PlotPixel16 function? It takes three numbers as parameters and pokes a single, colored pixel into the GBA's video RAM, which is the region of memory that stores the screen as a long series of color values.

You already figured out that the following function call draws a yellow pixel in the center of the screen:
Code:
PlotPixel16(120,80,yellow);


Here's a bit of code that does the same thing, but does so by passing two variables instead of fixed numbers.
Code:
int x;  // creates an integer (int) variable called "x"
int y; // creates an integer variable called "y"
x=120; // stores the number "120" into x
y=80; // stores the number "80" into y
PlotPixel16(x,y,yellow); // draws a yellow pixel at screen position x,y


Get it? Functions can be passed either fixed values OR the values that are stored in variables. Now, let's *alter* the value of y and call our function a second time. Replace the code above with the following:

Code:
int x;  // creates an integer (int) variable called "x"
int y; // creates an integer variable called "y"
x=120; // stores the number "120" into x
y=80; // stores the number "80" into y
PlotPixel16(x,y,yellow); // draws a yellow pixel at screen position x,y
y = y + 1; // adds "1" to y. After this line of code, y will contain "81"
PlotPixel16(x,y,yellow); // draws a yellow pixel at screen position 120,81


Run this and you'll see two yellow pixels on the screen. Even though the PlotPixel function call looks exactly the same on both lines, the fact that you altered Y between calls means that the pixel location changed.

2. Change X and Y inside the WHILE loop

The while(1) {} line inside your code is a "while loop", which is a way to repeat code execution in C. Any lines of code that you put between the curly brackets {} will be repeated over and over again so long as the expression inside the round parentheses () is "true." In this case, the number "1" always evaluates to true, so any lines of code you put between the brackets will repeat forever.

Try replacing the while(1) {} line with the following bit of code. Can you predict what this will do?

Code:

x = 120;
y = 0;

while(y<160)  // do this over and over until y >= 160
{
  y=y+1;
  PlotPixel16(x,y,yellow);
}

while (1) {} // do this loop forever


This (should) draw a yellow line from the top of the screen to the bottom.

Try these couple of exercises first, and write us back with how it went. The next steps from here are:

3. Getting user input on the GBA
(Hint: the GBA doesn't have cin, but there are macros in gba.h that tell you whether the user is pressing any of the buttons.)

4. Making user input change variables inside the while loop
(Hint: If the user presses "left" on the pad, change X, then draw a new pixel at X,Y, etc.)

5. Checking for "going off the screen"
(Hint: It's all about C's if/then code structure.)

6. Color macros
(Hint: You'll need to understand bit shifting and what a macro is.)
_________________
Some of my GBA projects

#146255 - speedemon35 - Sat Dec 01, 2007 3:14 pm

ScottLininger I'd like to thank you very very much for that:) Your post got me through a great deal of my troubles and i managed to hand in my project.

Also sorry for only replying back now but my internet sort of has a will of its own and i had other course work to do all the time so:(

and btw Scott your website is down which is quite a shame. I?m sure it would prove to be quite a handy learning resource

This is what the code looks like. According to the teacher its not the best code speed wise but i really couldn't care too much about that right now. important thing is that it works

Code:
//Add the header
#include "gba.h"

//Define the constants
#define BG2_ENABLE      0x400   
#define MODE3         0x3
#define FRONTBUFFER      (u16*)0x6000000

#define RGB(r,g,b) ((b<<10)+(g<<5)+r) //u16 --> unsigned short, this is the macro for RGB() 15bit color format
#define ScreenWidth 240
#define ScreenHeight 160

//Define a couple of colors for the pixel
#define Black 0x0000
#define White 0xFFFF
#define Cyan 0xFF00
#define Magenta 0xF00F
#define Yellow 0x0FDF
#define Blue 0xEE00
#define Red 0x00FF
#define Green 0x0EE0
#define Brown 0x0D0D
#define Gray 0x0B0B
#define Dark_gray 0x0D0D
#define Light_blue 0x0B0F
#define Light_green 0x0B0D
#define Light_cyan 0x0F0D
#define Light_magenta 0x0F00

//Key Definitions from Nokturn's key demo
#define KEY_A 1
#define KEY_B 2
#define KEY_SELECT 4
#define KEY_START 8
#define KEY_RIGHT 16
#define KEY_LEFT 32
#define KEY_UP 64
#define KEY_DOWN 128
#define KEY_R 256
#define KEY_L 512

//Global variables
u16* g_uspVideoBuffer   = FRONTBUFFER; //This is where we are currently drawing

volatile int* KEYS = (volatile int*)0x04000130;
short col[14];
bool buttons[10];

/*Function: PlotPixel16(int, int, unsigned short int)
  Notes: Plots a pixel in the specified colour*/

void PlotPixel16(int X,int Y, unsigned short int colour)
{
   g_uspVideoBuffer[(Y) * ScreenWidth + (X)] = (colour);
}


//=================
//   Function: clearscreen()
//      notes: refreshes screen by filling all pixels in black
//=================
void clearscreen()
{
   int x, y;
   unsigned short black= RGB(0,0,0);
   
   for ( x = 0; x < (ScreenWidth); x+=1)
   {
      for ( y = 0; y < (ScreenHeight); y+=1)
      {PlotPixel16(x,y,black);}
   }
}

//================
//   Function: checkbuttons()
//      notes: polls the status of all the buttons
//================
void checkbuttons()
{
   buttons[0] = !((*KEYS) & KEY_A);
   buttons[1] = !((*KEYS) & KEY_B);
   buttons[2] = !((*KEYS) & KEY_UP);
   buttons[3] = !((*KEYS) & KEY_DOWN);
   buttons[4] = !((*KEYS) & KEY_LEFT);
   buttons[5] = !((*KEYS) & KEY_RIGHT);
   buttons[6] = !((*KEYS) & KEY_START);
   buttons[7] = !((*KEYS) & KEY_SELECT);
   buttons[8] = !((*KEYS) & KEY_L);
   buttons[9] = !((*KEYS) & KEY_R);
}

int main()
{

   /*REG_DISPCNT (defined in gba.h) is the main display register that controls
     the mode of operation which backgrounds are enabled and which buffer is
     currently being drawn by the GPU.   This sets the screen mode to mode 3
     and enables background 2 which is required for all bitmap modes(3-5)*/
   REG_DISPCNT = MODE3 | BG2_ENABLE;
   
   col[0] = White;
   col[1] = Cyan;
   col[2] = Magenta;
   col[3] = Yellow;
   col[4] = Red;
   col[5] = Blue;
   col[6] = Green;
   col[7] = Brown;
   col[8] = Gray;
   col[9] = Dark_gray;
   col[10] = Light_blue;
   col[11] = Light_green;
   col[12] = Light_cyan;
   col[13] = Light_magenta;

   int n = 5; //counter for color change
   
   int x = 50;
   int y = 50;

   //draw the yellow pixel on the GBA screen
   PlotPixel16(x,y,Yellow);
   
   //loop to change pixel color depending on what buttons the user presses. If the correct buttons are pressed pixel changes color
   while(1)
   {
      checkbuttons();
      
      if (buttons[2])
      {
         if (y > 0)
         {clearscreen(); y = y - 1; PlotPixel16(x,y,col[n]);}
      }
      if (buttons[3])
      {
         if (y < (ScreenHeight - 1))
         {clearscreen(); y = y + 1; PlotPixel16(x,y,col[n]);}
      }
      if (buttons[4])
      {
         if ( x > 0 )
         {clearscreen(); x = x - 1; PlotPixel16(x,y,col[n]);}
      }
      if (buttons[5])
      {
         if ( x < (ScreenWidth - 1))
         {clearscreen(); x = x + 1; PlotPixel16(x,y,col[n]);}
      }   
      if (buttons[0])
      {
         switch (n)
         {
            case 0: {n = 1; break;}
            case 1: {n = 2; break;}
            case 2: {n = 3; break;}
            case 3: {n = 4; break;}
            case 4: {n = 5; break;}
            case 5: {n = 6; break;}
            case 6: {n = 7; break;}
            case 7: {n = 8; break;}
            case 8: {n = 9; break;}
            case 9: {n = 10; break;}
            case 10: {n = 11; break;}
            case 11: {n = 12; break;}
            case 12: {n = 13; break;}
            case 13: {n = 0; break;}
            PlotPixel16(x,y,col[n]);
         }
      }
      if (buttons[1])
      {
         switch (n)
         {
            case 0: {n = 6; break;}
            case 1: {n = 0; break;}
            case 2: {n = 1; break;}
            case 3: {n = 2; break;}
            case 4: {n = 3; break;}
            case 5: {n = 4; break;}
            case 6: {n = 5; break;}
            case 7: {n = 8; break;}
            case 8: {n = 9; break;}
            case 9: {n = 10; break;}
            case 10: {n = 11; break;}
            case 11: {n = 12; break;}
            case 12: {n = 13; break;}
            case 13: {n = 0; break;}
            PlotPixel16(x,y,col[n]);
         }
      }
   }
   
   return 0;
}