What Am I Doing Wrong?


TheMrCul

Still Fresh
Joined
Apr 18, 2003
Messages
52
Hi everyone
I just got a GP2X the other day and was porting a small game I was making using SDL over to GP2X. I am using Octate's all in one sdk, and a modified makefile from guyfawkes demo app provided in the sdk. I played around a lot with GP32 and the game I made in SDL for GP2X is very similar to another game I made for GP32. I got great performance on the GP32 (like 30fps+), but I can't get anything more than around 10 fps on the GP2X version! Every time I blit to screen the sky printing section, tiles printing section and status bar printing section each of them take a performance hit of around 50%! So if I just print one of them I'm fine, but each time I add sky, tiles etc to the mix, they each take a huge hit on performance. The hit they give isn't even as noticable as playing ogg files in the background! I'm really wondering what I'm doing wrong, is SDL and C++ at 200mhtz trully slower than a MrMirko and C on a GP32 at 80mhtz? I'll show you what I'm doing. (BTW, this same code runs WAY to fast on my PC, like 120 frames a second or more.
I load my graphics (24bit BMPs) like this:
SDL_Surface* TitleScreenPic = SDL_LoadBMP("Graphics/Screen.bmp");
etc.
I make my characters have a transparency like:
SDL_SetColorKey(PNormal, SDL_SRCCOLORKEY, 0xFF00FF);

My sky is just blitting 2 bitmaps of size 256 by 50 on the screen, (no transparency or alpha)
My tiles are 24by24 pixels at 24bit and are printed using a very standard blitting function: (no transparency or alpha here either)

Code:
void drawTiles()
{
	int ScreenWidth, ScreenHeight, XTile, YTile, XPos, YPos, Tile;

	//Get the starting tile to draw with
	XTile = CameraX / TileSize;
	YTile = CameraY / TileSize;

	//The pixel offset
	XPos = CameraX % TileSize;
	YPos = CameraY % TileSize;

	//Now draw the tiles
	for(ScreenWidth = 0; ScreenWidth < 15; ScreenWidth++) //across the screen in increments of 20
	{
		for(ScreenHeight = 0; ScreenHeight < 9; ScreenHeight++) //down the screen, increments of 20
		{
			//Get the tile number to draw and then draw it
			Tile = Map[YTile + ScreenHeight][XTile + ScreenWidth];

			//if(Tile > -1)
			drawSprite(Tiles, Screen,
				ScreenWidth * TileSize - XPos,
				ScreenHeight * TileSize - YPos + 30,
				Tile * TileSize, 0, TileSize, TileSize);
		}
	}
}

My characters are printed from a vector list of pointers to them, then going through the list and printing each of them by calling their printCharacter(); function. They are 47by28 pixels at 24bpp. (with transparency)

My status bar printing function prints a 320 by 50 pixel bar up the top, and a 320 by 50 bar down the bottom of the screen. (no transparency or alpha)

I also handle the input the way I see it done in all the tutorials I've read:

Code:
while(SDL_PollEvent(&event))
{
	switch (event.type)
	{
		//Joystick input
		case SDL_JOYBUTTONDOWN:
			switch(event.button.button)
			{
				case GP2X_BUTTON_UP:
					upKey = 1;
					break;
				case GP2X_BUTTON_DOWN:
					downKey = 1;
					break;
				case GP2X_BUTTON_LEFT:
					leftKey = 1;
					break;
				case GP2X_BUTTON_RIGHT:
					rightKey = 1;
					break;
				case GP2X_BUTTON_A:
					aKey = 1;
					break;
				case GP2X_BUTTON_B:
					bKey = 1;
					break;
				case GP2X_BUTTON_X:
					cKey = 1;
					break;
				case GP2X_BUTTON_Y:
					dKey = 1;
					break;
				case GP2X_BUTTON_VOLDOWN:
					volDown = 1;
					Mute = 0;
					break;
				case GP2X_BUTTON_VOLUP:
					volUp = 1;
					break;
				case GP2X_BUTTON_START:
					startKey = 1;
					break;
			}
			break;
		case SDL_JOYBUTTONUP:
			switch(event.button.button)
			{
				case GP2X_BUTTON_UP:
					upKey = 0;
					break;
				case GP2X_BUTTON_DOWN:
					downKey = 0;
					break;
				case GP2X_BUTTON_LEFT:
					leftKey = 0;
					break;
				case GP2X_BUTTON_RIGHT:
					rightKey = 0;
					break;
				case GP2X_BUTTON_A:
					aKey = 0;
					break;
				case GP2X_BUTTON_B:
					bKey = 0;
					break;
				case GP2X_BUTTON_X:
					cKey = 0;
					break;
				case GP2X_BUTTON_Y:
					dKey = 0;
					break;
				case GP2X_BUTTON_VOLDOWN:
					volDown = 0;
					//Lower the volume by 10
					if(GameVolume > 0)
						changeVolume(-10);

					ShowVolume = 1;
					break;
				case GP2X_BUTTON_VOLUP:
					volUp = 0;
					//If Mute is on, turn off (turn volume back on again)
					if(Mute == -1)
					{
						Mute = 0;
						changeVolume(OrigVolume);
					}
					else
					{
						changeVolume(10);
					}
					ShowVolume = 1;
					break;
				case GP2X_BUTTON_START:
					startKey = 0;
					break;
			}
			break;
		case SDL_QUIT:
			QuitGame = 2;
			break;
	}
}



So all my render engine is is:
Code:
void render(void)
{
	//Draw the sky (Behind the tiles)
	drawSky();

	//Draw the tiles
	drawTiles();

	//Go through the linked list and draw all characters on list
	drawCharacters();

	//Do the final draw, the
	drawStatusBar();

	SDL_Flip(Screen);
}

and my game engine is just:
Code:
while(!quit)
{
		renderEverything();

		#include "HandleInput.h"
}

the code to draw is just:
Code:
void drawSprite(SDL_Surface* imageSurface, SDL_Surface* screenSurface, int dstX, int dstY, int srcX, int srcY,  int width, int height)
{
	SDL_Rect srcRect;
	srcRect.x = srcX;
	srcRect.y = srcY;
	srcRect.w = width;
	srcRect.h = height;

	SDL_Rect dstRect;
	dstRect.x = dstX;
	dstRect.y = dstY;
	dstRect.w = width;
	dstRect.h = height;

	SDL_BlitSurface(imageSurface, &srcRect, screenSurface, &dstRect);
}

BTW my makefile is this:

Code:
CROSS_COMPILE = C:/devkitGP2X/bin/arm-linux-
SDL_BASE = C:/devkitGP2X/bin/arm-linux-
LDFLAGS = -static

CXX = $(CROSS_COMPILE)g++
STRIP = $(CROSS_COMPILE)strip

CXXFLAGS = -I"C:/devkitGP2X/include" -I"C:/devkitGP2X/include/SDL" -mcpu=arm920 -mtune=arm920t -O3 -fstrict-aliasing -fexpensive-optimizations -falign-functions -fweb -frename-registers -fomit-frame-pointer -ffast-math -finline-functions -fno-builtin -fno-common -mstructure-size-boundary=8 -msoft-float
LIBS = -s -L"C:/devkitGP2X/lib" -lSDL -lSDL_gfx --start-group -lSDL_ttf -lfreetype -lSDL --end-group -lSDL_image -ljpeg -lpng12 -lz --start-group -lSDL_mixer -lvorbisidec -lmikmod -lsmpeg -lSDL --end-group -lgcc -lm -lc -lexpat -lpthread -ldl

TARGET = GPThug2x.gpe
OBJS = GPThug2x.o

ALL_TARGETS = $(TARGET)

all: $(ALL_TARGETS)

$(TARGET): $(OBJS)
		$(CXX) $(LDFLAGS) -o $(TARGET) $(OBJS) $(LIBS)


clean:
		rm *.o
		rm $(TARGET)

I don't understand what I am doing wrong, as I thought this would run fine! :unsure: Can someone point out what I am doing wrong please? Thankyou all very much.
 
Are you running the game from the menu or through a telnet session? If it's through telnet then be careful because you're probably running at 100mhz. Also, make sure the surface you're blitting to is 16bit because anything higher is quite a lot slower.
 
My tiles are 24by24 pixels at 24bit and are printed using a very standard blitting function: (no transparency or alpha here either)

That could be your problem right there. The linux frame buffer is 16-bit, so using 24 bit tiles may result in a large amount of processing to change everything to 16-bit.

Woogal: I've noticed that if you telnet in and "killall gp2xmenu" in fw2.0, the menu blanks the screen and sets the speed back to 200mhz just before it exits. If you kill the menu via other means, it can leave the processor speed at 100mhz.
 
thanks for the replies Squidge and Woogal!
I'm not killing the menu or setting the MHtz in any way, and am just compling, copying to sd and then running from the main menu on the gp2x. Will killing the menu help? If so, how do I kill the menu (and where? is it in the main code or makefile?) or can I just set the cpu at 200 when I run the program? What is the command for that? Thanks for your help.
 
If you're just using the menu then there's nothing to worry about - the menu automatically sets the clock back to 200mhz before running an app.

Squidge: Ah, I'm glad they got that sorted out :). I've always used serial and had to the kill the menu with ctrl-c which kept the speed at 100mhz, but I got a new laptop the other day with no serial so I'll be using telnet over usb from now on.
 
Try LoadBMPing to a temporary surface then using SDL_DisplayFormat to convert it to 16-bit. It should make blitting faster.
 
@vimacs: The devkit already includes Paeryn's HW accelerated SDL.

@themrcul: Did you try to change the color depth to 16bit and did it speed up your application?
 
Back
Top