Page 1 of 1

How can I layer TIM's and use multiple CLUT's?

Posted: July 21st, 2012, 11:05 pm
by Shadow
How can I layer TIM's like the image below?
Image
tim_layering.png
Thanks

Re: How can I layer TIM's?

Posted: July 29th, 2012, 11:45 am
by Mdrb
Well I think it depends of the way you display these TIMs on screen.

If your TIMs are smaller than 256*256px, the easiest way is, in my opinion, to use a GsSPRITE structure and display them by calling the GsSortSprite function. The third parameter is its position in the ordering table, and if I'm remember well, the bigger this value is, the nearest from the camera the sprite will be (a kind of z-index).
Also note that the order in which the different calls to GsSortSprite are made doesn't affect the result. So calling GsSortSprite(&spr1, ot, 8); and then GsSortSprite(&spr2, ot, 4); will display spr2 below spr1.

Another way could be to use MoveImage(), but that's a bit more complicated because it's a non-blocking function, so you need to call DrawSync (or use DrawSyncCallback) after each MoveImage call to wait the drawing function ends (well, that's what the libref46.pdf say, I haven't tried yet).

I hope this may help you! :P

Re: How can I layer TIM's?

Posted: July 29th, 2012, 2:36 pm
by Shadow
Hmm... I just tried and it did not work.

Re: How can I layer TIM's?

Posted: July 30th, 2012, 2:22 am
by isufje
No, it does work.

GsSortSprite(&tim3, ot, 0);
GsSortSprite(&tim2, ot, 0);
GsSortSprite(&tim1, ot, 0);

^works. tim3 gets drawn on top. tim2 gets drawn down one. tim1 gets drawn down one more. (That's the way i do it anyway)

Re: How can I layer TIM's?

Posted: July 30th, 2012, 7:13 am
by Mdrb
the bigger this value is, the nearest from the camera the sprite will be
Whoops sorry, that's the contrary :oops:

You can also try like that, it should work :

Code: Select all

GsSortSprite(&tim1, ot, 2);
GsSortSprite(&tim2, ot, 1);
GsSortSprite(&tim3, ot, 0);
The GPU will draw tim1 in first since its priority in ot is the highest, then tim2 (which will recover tim1), and finaly tim3 (which will recover tim2 and tim1).

Re: How can I layer TIM's?

Posted: September 4th, 2012, 8:44 pm
by Shadow
Okay, I finally got around to fixing my code up and it works fantastically. Thank you mdrb and isufje!

A problem I am having now is that the colours of the image on top of the other image seems to be inverted.
IE: blue becomes black, white becomes green, green becomes yellow, and so on.

Re: How can I layer TIM's and use multiple CLUT's?

Posted: September 7th, 2012, 1:29 am
by Mdrb
Hi Shadow, I'm happy to see that you finally managed to get your code working ! :clap
I think my CLUT from the first image is getting used on the second image.
That's also the first thing I though while reading your message. I suggest you to :
- try with some 16bit TIMs, just to be sure this is really a CLUT problem
- edit the CLUT position of your TIMs in the framebuffer memory with TimTool (it looks like a line of colored pixels). Be sure there's no CLUT overriding.
- modify the function you use to load the TIM files (eg: specifying an argument to TRUE if your loading function have to load the CLUT of the TIM (no need to load the CLUT of all your TIMs files if they share the same color palette) .

Here is a function I use to load TIMs located in memory. It's extracted from my files, so it may probably not work as is (I've commented the debug function and added some comments). Maybe it may inspired you to write your own.

Code: Select all

/* This is a header value stored at the beginning at the TIM file */
#define TIM_HEADER 0x00000010

/**
 * Transfer a TIM file from main memory to the video frame buffer.
 *
 * @param addr_tim Pointer to the TIM in memory
 * @param img_info Pointer to a GsIMAGE structure in which the image informations will be stored
 */
void
tim_load_from_mem(u_long *addr_tim, GsIMAGE *img_info)
{
	/* Position in the framebuffer where the image will be loaded */
	RECT 	img_rect;

	/* Checks the header of the file, to be sure it's a TIM file */
	if (*addr_tim != TIM_HEADER)
	{
		// debug_printf(DEBUG_LOG, "error: not a tim file");
		return;
	}

	// debug_printf(DEBUG_LOG, "loading tim from mem");

	/* Skip this header */
	addr_tim++;

	/* Extract the image info from the TIM file */
	GsGetTimInfo(addr_tim, img_info);

	/* Set the position rect in the framebuffer */
	img_rect.x = img_info->px;
	img_rect.y = img_info->py;
	img_rect.w = img_info->pw;
	img_rect.h = img_info->ph;

	/* Transfer the pixels of the image in the framebuffer */
	LoadImage(&img_rect, img_info->pixel);
	
	/* LoadImage is a non blocking function, so we need to vait the loadng finished */
	DrawSync(0);
	
	// debug_printf(DEBUG_LOG, "pmode: %lu", img_info->pmode);

	/* If a CLUT exists in the TIM, transfer it in VRAM */
/*
16bits: pmode=2,  0010b
 8bits: pmode=9,  1001b
 4bits: pmode=8, 1000b
Only 8 et 4 bits uses a CLUT.
*/

	if ((img_info->pmode >> 3) & 0x1)
	{
		// debug_printf(DEBUG_LOG, "loading tim clut");

		img_rect.x = img_info->cx;
		img_rect.y = img_info->cy;
		img_rect.w = img_info->cw;
		img_rect.h = img_info->ch;

		LoadImage(&img_rect, img_info->clut);
		DrawSync(0);
	}
}
Good luck ;)

(If I've understood well, a CLUT looks like a 16bits image of 256*1px, where each pixel defines a palette entry, so loading a clut is similar to loading an image)

Re: How can I layer TIM's and use multiple CLUT's?

Posted: September 7th, 2012, 1:22 pm
by isufje
simple, turn off gawd damm transparency. problem solved.

Re: How can I layer TIM's and use multiple CLUT's?

Posted: September 7th, 2012, 4:24 pm
by Shadow
Nope. Not a transparency issue.

When I ran my program, the animation would cycle through, and at the top of the image there was some flickering. I had just ignored it all this time. The problem was that it was the CLUT being drawn. So, there were tiny pixels and then a huge black line drawn across the top. I loaded the TIM into TIMTOOL, and noticed it was being draw in first buffer. So, I moved it over a few hundred pixels, and it was gone (I also had to change the logic in my code to compensate for the adjustment). The next problem was that the layered image was no longer being drawn, or, the screen would go crazy. This was because the CLUT I just moved over was mixing with the second image. In the end, I got it all working fine. It was just because I mixed all the images CLUT's together :naughty