OAM is screwing me.

Post Reply
relminator
Posts: 84
Joined: Sun Apr 11, 2010 10:43 am

OAM is screwing me.

Post by relminator » Fri Jul 23, 2010 7:55 am

Hi. Dunno if cross-posting here and gbadev is allowed but I thought the more people see my prob the better.

I've just implemented my oamfont(font are rendered via oam) since my sub screen font needs are not that much and I needed the speed.

However an artifact shows on one of the text printed on the sub screen and the weird thing is that it only shows on start up. I'm pretty sure it's the oam trying to screw me because I've implemented the same font system using the gl interface and it worked like a charm. I've been trying to find out the bug to no avail for hours now.

My eyes are not that fast to discern but I think the oam gets flipped.

Code: Select all

/******************************************************************************
*******************************************************************************

	Space Impakto DS
	relminator
	http://rel.betterwebber.com


	Coamfont class


*******************************************************************************
******************************************************************************/

#include <nds.h>
#include "Coamfont.h"



/******************************************************************************



******************************************************************************/
void Coamfont::init(OamState *_oam,u8 *_gfx, int _width, int _height, SpriteSize _size, int _max_chars)
{
	active_chars = 0;
	oam = _oam;
	
	if (_max_chars > MAX_FONT_SPRITES)
		_max_chars = MAX_FONT_SPRITES;
	
	gfx = _gfx;
	max_chars = _max_chars;
	width = _width;
	height = _height;
	tile_mem_size = width * height;
	
	fonts[0].create (oam, width, height, _size, SpriteColorFormat_256Color, true, true);
	fonts[0].active = false;
	
	for (int i = 1; i < max_chars; i++)
	{
		fonts[i].create (oam, width, height, _size, SpriteColorFormat_256Color, true);
		fonts[i].active = false;
	}

}

/******************************************************************************



******************************************************************************/
void Coamfont::clear()
{
	active_chars = 0;
	for (int i = 0; i < max_chars; i++)
	{
		fonts[i].active = false;
	}

}

/******************************************************************************



******************************************************************************/
void Coamfont::print(int x, int y, const char *text)
{

	unsigned char font_char;
	
	while(*text)
	{
		font_char = (*(unsigned char*)text++) - 32;
		if (font_char)	// don't print space
		{
			for (int i = 0; i < max_chars; i++)
			{
				if (!fonts[i].active)
				{
					dmaCopy(gfx + (tile_mem_size*font_char) , fonts[i].gfx, tile_mem_size);
					fonts[i].active = true;
					fonts[i].x = x;
					fonts[i].y = y;
					fonts[i].update_oam();
					active_chars++;
					break;
				}
			}
		}
		x += width; 
	}
	
}

/******************************************************************************



******************************************************************************/
void Coamfont::print(int x, int y, int value)
{

	
	sprintf(str,"%i",value);
	
	print(x, y, str);
	
}

/******************************************************************************



******************************************************************************/
void Coamfont::print(int x, int y, const char *text, int value)
{

	strcpy(str, text);
	sprintf(str2,"%i",value);
	strcat(str, str2);
	
	print(x, y, str);
	
}

/******************************************************************************



******************************************************************************/
void Coamfont::print_centered(int x, int y, const char *text)
{

	unsigned char font_char;
	int total_width = 0;
	
	total_width = width * strlen(text);
	
	x = (SCREEN_WIDTH - total_width) / 2; 
	
	
	while(*text)
	{
		font_char = (*(unsigned char*)text++) - 32;
		if (font_char)	// don't print space
		{
			for (int i = 0; i < max_chars; i++)
			{
				if (!fonts[i].active)
				{
					dmaCopy(gfx + (tile_mem_size*font_char) , fonts[i].gfx, tile_mem_size);
					fonts[i].active = true;
					fonts[i].x = x;
					fonts[i].y = y;
					fonts[i].update_oam();
					active_chars++;
					break;
				}
			}
		}
		x += width; 
	}
	
}

/******************************************************************************



******************************************************************************/
void Coamfont::print_score(int x, int y, int value, const char *filler, int length)
{

	sprintf(str2,"%i",value);
	int value_len = strlen(str2);
	
	if (length < value_len)
		length = value_len;
		
	int new_length = length - value_len;
	
	for (int i=0; i < new_length; i++)
	{
		str[i]=*filler;
	}
	
	//str[new_length]='\0';			// not needed
	
	char *p_str = &str[new_length];
 
	strcpy(p_str, str2);
	
	print(x, y, str);
	
}

/******************************************************************************



******************************************************************************/
void Coamfont::print_spaced(int x, int y, const char *text, int x_space, s32 x_offset, s32 y_offset)
{

	unsigned char font_char;
	s32 spacing = x_space << 12;
	s32 y_spacing = 0;
	s32 _x = x << 12;
	s32 _y = y << 12;
	s32 _x_space = x_space << 12;
	
	while(*text)
	{
		font_char = (*(unsigned char*)text++) - 32;
		if (font_char)	// don't print space
		{
			for (int i = 0; i < max_chars; i++)
			{
				if (!fonts[i].active)
				{
					dmaCopy(gfx + (tile_mem_size*font_char) , fonts[i].gfx, tile_mem_size);
					fonts[i].active = true;
					fonts[i].x = _x >> 12;
					fonts[i].y = _y >> 12;
					fonts[i].update_oam();
					active_chars++;
					break;
				}
			}
		}
		
		y_spacing += y_offset;
		
		spacing += x_offset;
		_x_space = spacing;
		
		_x += ((width<<12) + _x_space); 
		_y += (y_spacing);
	}
	
}

/******************************************************************************



******************************************************************************/
void Coamfont::print_vertical(int x, int y, const char *text)
{

	unsigned char font_char;
	
	while(*text)
	{
		font_char = (*(unsigned char*)text++) - 32;
		if (font_char)	// don't print space
		{
			for (int i = 0; i < max_chars; i++)
			{
				if (!fonts[i].active)
				{
					dmaCopy(gfx + (tile_mem_size*font_char) , fonts[i].gfx, tile_mem_size);
					fonts[i].active = true;
					fonts[i].x = x;
					fonts[i].y = y;
					fonts[i].update_oam();
					active_chars++;
					break;
				}
			}
		}
		y += height; 
	}
	
}



Anyways here's the full source and binary:
(Look at the moving "ANYATECH" text at the bottom.)

http://rel.betterwebber.com/junk.php?id=111


And for the glfont routine that works perfectly:

http://rel.betterwebber.com/junk.php?id=110


Thanks in advance!

zeromus
Posts: 212
Joined: Wed Mar 31, 2010 6:05 pm

Re: OAM is screwing me.

Post by zeromus » Fri Jul 23, 2010 8:52 pm

You have a big problem: you can't alter obj memory the way you are in the middle of a frame. Oams are pointing at it and rendering, and youre changing what theyre displaying. This creates a temporary mismatch between obj and oam.

Second, a bug, which you have now and might still have after addressing the above point: you alter obj memory (with dmaCopy) but may be missing the start of vblank. so youll end up waiting that means, in the subsequent frame, you will have mismatching obj and oam.

The solution is to doublebuffer.

In your case you might get easy mileage out of not clearing active_chars, but letting it wrap around. This will effectively multi-buffer your obj tiles. But I wonder why you can't just load obj with your font once and be done with it.

relminator
Posts: 84
Joined: Sun Apr 11, 2010 10:43 am

Re: OAM is screwing me.

Post by relminator » Sat Jul 24, 2010 2:36 am

I wanted to have a dynamic font routine that could change text on the fly. But I guess it's not really that easy.

Thanks!

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests