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 > ndefined reference problem

#10377 - goro - Wed Sep 03, 2003 5:05 pm

Hi,

I'm working on GBA Junkies tutorial 6 (maps) and when I try to compile I get :


Code:
--------------------Configuration: 2 - Win32 Debug--------------------
Microsoft (R) Program Maintenance Utility   Version 6.00.8168.0
Copyright (C) Microsoft Corp 1988-1998. All rights reserved.
 c:\devkitadv\bin\ld -L c:\devkitadv\lib\gcc-lib\arm-agb-elf\3.0.2\interwork -L c:\devkitadv\arm-agb-elf\lib\interwork -T LinkScript -o 2.elf crt0.o        crtbegin.o    crtend.o      interupt.o    2.o -lstdc++ -lgcc -lc
2.o: In function `main':
C:/PROJECTS/GBA/2/2.cpp:90: undefined reference to `sin'
C:/PROJECTS/GBA/2/2.cpp:91: undefined reference to `cos'
C:/PROJECTS/GBA/2/2.cpp:109: undefined reference to `EnableBackground(Bg*)'
C:/PROJECTS/GBA/2/2.cpp:128: undefined reference to `RotateBackground(Bg*, int, int, int, long)'
C:/PROJECTS/GBA/2/2.cpp:130: undefined reference to `UpdateBackground(Bg*)'
NMAKE : fatal error U1077: 'c:\devkitadv\bin\ld' : return code '0x1'
Stop.
Error executing NMAKE.

2.exe - 1 error(s), 0 warning(s)


I cut&pasted it so it is exactly as he wrote it :-
Code:

//////////////////////////////////////////////////////////////////////////
// File:    ch6a.cpp                                               //
// Description: A program that displays a 128x128 background map   //
// Author:   gbajunkie                     //
// Date:    24th April 2002                                         //
//////////////////////////////////////////////////////////////////////////
#include<math.h>    //sign and cos stuff
#include"gba.h"         //GBA register definitions
#include"dispcnt.h"     //REG_DISPCNT register #defines
#include"keypad.h"      //button registers
#include"bg.h"          //background definitions

//my graphics data produced by pcx2sprite program
#include"exptiles.h"

//data produced by map editor
#include"128128map.c"

//Rotation variables (don't worry about them here) done in later chapter
/**********************************************************************************/
FIXED angle = 0;
FIXED zoom = 1<<8;  //zoom is a fixed point number

FIXED SIN[360];       //Look-Up Tabless for sign and cosign
FIXED COS[360];

char RotIndexCounter = 0;  //global to keep track of rotation indexes used
/**********************************************************************************/

//declare an instance of the background structure
Bg bg2;

//wait for the screen to stop drawing
void WaitForVsync()
{
   while((volatile u16)REG_VCOUNT != 160){}
}

///Test for key presses
void GetInput()
{
   if(!(*KEYS & KEY_UP))
   {
      bg2.y_scroll++;
   }
   if(!(*KEYS & KEY_DOWN))
   {
      bg2.y_scroll--;
   }
   if(!(*KEYS & KEY_LEFT))
   {
      bg2.x_scroll++;
   }
   if(!(*KEYS & KEY_RIGHT))
   {
      bg2.x_scroll--;
   }
   if(!(*KEYS & KEY_L))
   {
       angle--;
      if(angle<0)
         angle = 359;
   }
   if(!(*KEYS & KEY_R))
   {
       angle++;
      if(angle > 359)
         angle = 0;
   }
   if(!(*KEYS & KEY_A))
   {
       zoom--;
   }
   if(!(*KEYS & KEY_B))
   {
       zoom++;
   }
}

///main entry point from the boot.asm startup file
int main()
{
   int index = 0;  //generic loop variables
   u16 loop;
   u16* temp;      //temporary storage pointer

   //compute my Look up tables (Rotation stuff again)
   for(loop = 0; loop < 360; loop++)
   {
      SIN[loop] = (FIXED)(sin(RADIAN(loop)) * 256);  //sin and cos are computed and cast to fixed                     //fixed
      COS[loop] = (FIXED)(cos(RADIAN(loop)) * 256);
   }

   //set mode 2 and enable sprites and 1d mapping
   SetMode(MODE_1 | OBJ_ENABLE | OBJ_MAP_1D);

   //Let us set up the backgroud two structure and enable the background

   bg2.number = 2;            //background number 0-3
   bg2.charBaseBlock = 0;                  //tile data position (right at the start of the available memory on 16Kb boundary)
   bg2.screenBaseBlock = 28;      //map data position on 2Kb boundary
   bg2.colorMode = BG_COLOR_256;           //256-colour background
   bg2.size = ROTBG_SIZE_128x128;          //size of map
   bg2.mosaic = 0;                         //not enabled
   bg2.x_scroll = 120;         //scrolling variables
   bg2.y_scroll = 80;

   //Point to correct tile and map data, update the Background and Display registers accordingly
        EnableBackground(&bg2);



   for(loop = 0; loop < 256; loop++)
      BGPaletteMem[loop] = exptilesPalette[loop];     //load the background palette into memory

   for(loop = 0; loop < exptiles_WIDTH * exptiles_HEIGHT /2; loop++)  //load tile image data
      bg2.tileData[loop] = exptilesData[loop];

   //load the map image data
   temp = (u16*)map;
   for(loop = 0; loop < 16*16/2; loop++) //16x16 tiles /2 because 16 bit copy
      bg2.mapData[loop] = temp[loop];

   //Main Game loop
   while(1)
   {
      GetInput();    //check for input
      RotateBackground(&bg2,angle,119,79,zoom);    //rotates background if required (don't worry about this)
      WaitForVsync();               //waits for the screen to stop drawing
      UpdateBackground(&bg2); //make sure registers are updated if anything changes e.g. scrolling
   }
   return(0);
}


Please help!!!!

#10378 - tepples - Wed Sep 03, 2003 5:11 pm

"Undefined reference" errors returned by the linker usually mean you forgot to link in some object file or some library.

sin() and cos() are in .../lib/libm.a, which you link in by inserting -lm after all your object files in the linker command line.

There are two main reasons why finding EnableBackground() and friends would fail:
1. you're not linking in the object file that contains EnableBackground() and friends, or
2. you're trying to call a C++ function from C or vice versa. If you want to include a header file containing prototypes of C functions in your C++ program, you should place extern "C" { ... } around the #include statement that brings in the header file.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#10382 - goro - Wed Sep 03, 2003 7:21 pm

I think I have -lm in my makefile:-

Code:

path=C:\devkitadv\bin

g++  -o ch6b.elf ch6b.cpp bg.cpp  -lstdc++ -lm -lgcc -lc -lgcc

objcopy -O binary ch6b.elf ch6b.bin


can you confirm that it's ok or do I also have to specify it somewhere else?

Also enablebackground is in bg.h, which looks like this :-

Code:

#ifndef BG_H
#define BG_H


///BGCNT defines ///
#define BG_MOSAIC_ENABLE      0x40
#define BG_COLOR_256         0x80
#define BG_COLOR_16         0x0

#define CharBaseBlock(n)      (((n)*0x4000)+0x6000000)
#define ScreenBaseBlock(n)      (((n)*0x800)+0x6000000)

#define CHAR_SHIFT         2
#define SCREEN_SHIFT         8
#define TEXTBG_SIZE_256x256      0x0
#define TEXTBG_SIZE_256x512      0x8000
#define TEXTBG_SIZE_512x256      0x4000
#define TEXTBG_SIZE_512x512      0xC000

#define ROTBG_SIZE_128x128      0x0
#define ROTBG_SIZE_256x256      0x4000
#define ROTBG_SIZE_512x512      0x8000
#define ROTBG_SIZE_1024x1024      0xC000

#define WRAPAROUND                 0x1

typedef struct Bg
{
   u16* tileData;
   u16* mapData;
   u8 mosaic;
   u8 colorMode;
   u8 number;
   u16 size;
   u8 charBaseBlock;
   u8 screenBaseBlock;
   u8 wraparound;
   s16 x_scroll,y_scroll;
   s32 DX,DY;
   s16 PA,PB,PC,PD;
}Bg;

#ifndef BG_C
extern void EnableBackground(Bg* bg);
extern void RotateBackground(Bg* bg, int angle, int center_x, int center_y, FIXED zoom);
extern void UpdateBackground(Bg* bg);
#endif
#endif


I have '#included' it, do I have to specify elsewhere?

EDIT - I foung BG.cpp in the folder, how do I link this?
it looks like this :-
Code:

#define BG_C

#include "gba.h"
#include "bg.h"
#include "dispcnt.h"

extern FIXED COS[360];
extern FIXED SIN[360];

void EnableBackground(Bg* bg)
{
   u16 temp;

   bg->tileData = (u16*)CharBaseBlock(bg->charBaseBlock);
   bg->mapData = (u16*)ScreenBaseBlock(bg->screenBaseBlock);
   temp = bg->size | (bg->charBaseBlock<<CHAR_SHIFT) | (bg->screenBaseBlock<<SCREEN_SHIFT)
      | bg->colorMode | bg->mosaic | bg->wraparound;

   switch(bg->number)
   {
   case 0:
      {
         REG_BG0CNT = temp;
         REG_DISPCNT |= BG0_ENABLE;
      }break;
   case 1:
      {
         REG_BG1CNT = temp;
         REG_DISPCNT |= BG1_ENABLE;
      }break;
   case 2:
      {
         REG_BG2CNT = temp;
         REG_DISPCNT |= BG2_ENABLE;
      }break;
   case 3:
      {
         REG_BG3CNT = temp;
         REG_DISPCNT |= BG3_ENABLE;
      }break;

   default:break;

   }
}

void UpdateBackground(Bg* bg)
{
   switch(bg->number)
   {
   case 0:
      REG_BG0HOFS = bg->x_scroll;
      REG_BG0VOFS = bg->y_scroll;
      break;
   case 1:
      REG_BG1HOFS = bg->x_scroll;
      REG_BG1VOFS = bg->y_scroll;
      break;
   case 2:
      if(!(REG_DISPCNT & MODE_0))//it is a rot background
      {
         REG_BG2X = bg->DX;
         REG_BG2Y = bg->DY;

         REG_BG2PA = bg->PA;
         REG_BG2PB = bg->PB;
         REG_BG2PC = bg->PC;
         REG_BG2PD = bg->PD;
      }
      else  //it is a text background
      {
         REG_BG2HOFS = bg->x_scroll;
         REG_BG2VOFS = bg->y_scroll;
      }
      break;
   case 3:
      if(!(REG_DISPCNT & MODE_0))//it is a rot background
      {
         REG_BG3X = bg->DX;
         REG_BG3Y = bg->DY;

         REG_BG3PA = bg->PA;
         REG_BG3PB = bg->PB;
         REG_BG3PC = bg->PC;
         REG_BG3PD = bg->PD;
      }
      else //it is a text background
      {
         REG_BG3HOFS = bg->x_scroll;
         REG_BG3VOFS = bg->y_scroll;
      }
      break;
   default: break;
   }
}

void RotateBackground(Bg* bg, int angle,int center_x, int center_y, FIXED zoom)
{

   center_y = (center_y * zoom)>>8;
   center_x = (center_x * zoom)>>8;

   bg->DX = ((bg->x_scroll<<8)-center_y*SIN[angle]-center_x*COS[angle]);
   bg->DY = ((bg->y_scroll<<8)-center_y*COS[angle]+center_x*SIN[angle]);

   bg->PA = (COS[angle]*zoom)>>8;  //cos&sin are LUTs that are .8 fixed numbers
   bg->PB = (SIN[angle]*zoom)>>8;  //zoom is also fixed
   bg->PC = (-SIN[angle]*zoom)>>8;
   bg->PD = (COS[angle]*zoom)>>8;
}


How do I link it or make it work?

#10386 - tepples - Wed Sep 03, 2003 7:48 pm

There are three function prototypes at the end of the header file. Please remove the line #ifndef BG_C and one of the lines #endif . If something is going wrong when compiling bg.cpp, such as a function signature mismatch (which I'll explain if you turn out to have one), then this may show better error messages.

Another thing you should do is output a .gba file instead of a .bin file from objcopy. Many users have the .bin file extension associated to a Sega Genesis emulator rather than to a Game Boy Advance emulator. Do this by changing ch6b.bin in your objcopy file to ch6b.gba .
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#10391 - yaustar - Thu Sep 04, 2003 12:58 am

goro wrote:

EDIT - I foung BG.cpp in the folder, how do I link this?
it looks like this :-


You dont need to link it within the code...

You include it in the make.bat file which you already have....
Code:

path=C:\devkitadv\bin

g++  -o ch6b.elf ch6b.cpp bg.cpp  -lstdc++ -lm -lgcc -lc -lgcc

objcopy -O binary ch6b.elf ch6b.bin

_________________
[Blog] [Portfolio]

#10414 - goro - Thu Sep 04, 2003 11:36 am

Understood. Thanks for all the help you guys.

I think I have to get used to editing the make.bat file manually instead of allowing MS visual studio to do it for me.

I also found a different way to it (add the files to my 'PROJECT' and use 'rebuild all' in MS Visual Studio)
but I'm not sure if it adds -lm or any of the other required extra stuff.

Thanks again for all of your help.