Need some help regarding CLUT texture mode

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Need some help regarding CLUT texture mode

Post by Raphael »

Hello devs, I've got a problem with getting a CLUT4 program to run as it should.

First off, why does the following code crash, but the latter not?

Code: Select all

unsigned short __attribute__((aligned(16))) g_font_clut[16];

void clut_color( long color ) {
	unsigned short* clut = (unsigned short*)(((unsigned short)g_font_clut)|0x40000000);
	int i;
	for &#40;i=0;i<16;i++&#41;
		*&#40;clut++&#41; = &#40;&#40;i&#41; << 12&#41; | &#40;color & 0xFFF&#41;;
&#125;
But this won't crash:

Code: Select all

unsigned int __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; g_font_clut&#91;16&#93;;

void clut_color&#40; long color &#41; &#123;
	unsigned short* clut = &#40;unsigned short*&#41;&#40;&#40;&#40;unsigned int&#41;g_font_clut&#41;|0x40000000&#41;;
	int i;
	for &#40;i=0;i<16;i++&#41;
		*&#40;clut++&#41; = &#40;&#40;i&#41; << 12&#41; | &#40;color & 0xFFF&#41;;
&#125;
I suppose it's with the alignment, so that an array[16] of unsigned short cannot be aligned the way needed (aligned to 64 byte?)? I just want to make sure. If so, the notes in the sdk should be updated with correct alignment infos.

Then the other problem is, my texture won't be drawn correctly and I dug it out to the fact, that all indices drawn by GU from the texture are 0, even though when I just read through the texture array and print every index as int to a textfile, it shows correctly. So the problem must lie either in the texture upload, or in the texture mode parameters. I load the texture data from a file btw.

Code: Select all

unsigned char __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; g_font_tex&#91;256*128&#93;;

void drawstuff&#40;&#41;
&#123;
		sceGuClutMode&#40;GU_PSM_4444,0,0xff,0&#41;; // 16-bit palette
		sceGuClutLoad&#40;&#40;16/8&#41;,g_font_clut&#41;; // upload 2*8 entries &#40;16&#41;
		sceGuTexMode&#40;GU_PSM_T4,0,0,0&#41;; // 4-bit image
		sceGuTexImage&#40;0,256,256,256,g_font_tex&#41;;
		sceGuTexFunc&#40;GU_TFX_REPLACE,GU_TCC_RGBA&#41;;
		sceGuTexFilter&#40;GU_NEAREST,GU_NEAREST&#41;;
		sceGuBlendFunc&#40;GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0&#41;;
		sceGuEnable&#40; GU_BLEND &#41;;
...
&#125;
With this code, when I draw the whole texture on the screen, it's just completely transparent, but when I turn off blending, the whole rect is in the color chosen with clut_color. That's why all indices drawn must be zero (thus the alpha in the CLUT being 0).

EDIT: It's not a problem of the texture cash or DCash, as I just verified.

And for some clarification needs: What parameters am I really supposed to give the sceGuTexImage function with a 4bit indexed texture like above? Is the texture width and buffer width really 256 or should the one or the other be 128 (byte width)?

Thanks for your help :)
chp
Posts: 313
Joined: Wed Jun 23, 2004 7:16 am

Post by chp »

The palette-generation code you wrote crashes because you cast the pointer into an unsigned short, which will drop the top 16 bits of the address. The pointer should be case into something that matches the pointer-size (like unsigned int on PSP).
GE Dominator
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Ah, yes I see. Could have found that myself 8) Thanks for the info.

Still there's the problem with the texture not showing up correctly... it's really a hinderness. Any ideas there?
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Post by jsgf »

I have a suspicion the "num_blocks" parameter of sceGuClutLoad() depends on the format of the clut entries, rather than being a fixed /8 scaling. Try an RGB8888 clut, and/or playing with the num blocks parameter.
NPherno
Posts: 4
Joined: Wed Feb 08, 2006 7:06 pm

Various Palette/CLUT Notes...

Post by NPherno »

First, the ClutMode command's 3rd param isn't unknown... as the docs I last saw stated... none of them are.

Here's the documentation as I am aware of it...

sceGuClutMode(CLUTFORMAT, shift, mask, startentry);

This means you could load an 8Bit Indexed Texture, but with some calls use only the top 4 bits, and in other modes, use the bottom (play with shift if you want to see the effects). mask is literaly, after an index read & shift, the value is masked. The problem comes when you don't set the mask correctly (which appears to be your issue...). You only want 16 values... why use a 256 value mask? 0xF instead of 0xFF may end up being the solution (I initially defaulted to 0xFFFFFFFF, but wow... that didn't work at all... I got _only_ the low 4 bits of each index... maybe handy for you? :)

The mask has an odd effect that I've sort of gotten at above... even a 4bit index texture can read _much_ larger values into the CLUT indexing pipe... because if you mask at 0xFF for a CLUT4, you are getting _2_ pixels of index data... if you didn't load the CLUT correctly, you may be refering to CLUT entries that are zero... and well out of the range you are expecting.

the start entry is great... it allows for palette animation (1 CLUT page at a time...etc). A value of 0 means 0... a value of 1 means something depending on what format the CLUT is in... 4444 would be a 16 value offset, 8888 would be 8... basicly the same rules as the ClutLoad entry count value...

ClutLoad appears to need a bit more info too...

The entry count is defined as 32 bytes per value... so for a 16bit CLUT entry, you want sceGuClutLoad(1, ptr), for 16 entries ('cause each is 2 bytes, right?). For a ABGR (8888) CLUT, a value of 1 would get you only 8 CLUT entries loaded... so for a full 256 entires at 8bit index... you'd need to say '32' instead of 1 =-]

And when all else fails... change the order you do your state changes. Upload the texture, then set the mode, the load CLUT, or maybe load then mode... try them out... if _shouldn't_ matter... but I tend to think when you aren't seeing straight a few swapped lines of code might be the answer, and they often don't hurt.

N
NPherno
Posts: 4
Joined: Wed Feb 08, 2006 7:06 pm

Methods...

Post by NPherno »

I forgot to say much about how I determined most of this stuff...

First, when you load an 8bit image with a perfectly valid palette, and get _nothing_, you get creative :)

I setup my Palette loaded to fill the palette with a fully opaque color per entry, where the reds go up (0->255), and the blues go down (255->0)...

Every pixel of my texture was set to it's linear address. That way, I could see _something_, and begin to play with the various parameters of the mode/load/etc calls. After that, you end up with a very clean mental map (after a few hours) of how things work.

I often wonder how some programmers get along without a solid sense of problem solving and just general 'hacking' skills. There's an ordered way to resolve almost any unknown...

N
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Nice, thanks for all the enlightening informations :) I appreciate it.
I also finally got everything to work as I wanted, even though I didn't change the mask or the parameter for number of clut entries (Now I wonder why it still works, at least the latter, since I use 16bit palette entries and have 16 entries, so there should be 2*16 = 32byte / 8 = 4 'entries' submitted, however I call it with 16/8 = 2?).
Well, in the end my problem was that when I tried to use the blit sdk sample program for testing my stuff, I hadn't applied the path to the texture to load correctly. After this and some more playing around with the parameters I got something to display and then it was rather easy to fix finally. Thanks for all the help :)

Yet, I still don't understand the use for the fourth parameter of sceGuTexImage. Is it really always the same as the texture width? Or is it supposed to help when the image you send has a wider linesize than the actual texture? Like with 24bit bitmaps where bytesperline nonetheless is a mutiple of 32bit?
NPherno
Posts: 4
Joined: Wed Feb 08, 2006 7:06 pm

Post by NPherno »

Raphael = (Now I wonder why it still works, at least the latter, since I use 16bit palette entries and have 16 entries, so there should be 2*16 = 32byte / 8 = 4 'entries' submitted, however I call it with 16/8 = 2?)

I am not sure how you are getting the math you're using? :)

32bytes is 1 'entry' to ClutLoad. You need 16 palette slots... which is 32bytes, which is _1_ entry. So you are uploading twice what you need to.

As for GuTexImage... the 4th param is _critical_ for not only non-power-of-2 sized textures, as it allows you to define a stride that is closer to the literal size of the texture (it's always aligned to 16 bytes, regardless of pixel format), but also because it allows for packing tricks... such as textures loaded 'around' another texture's dead space (you know that 32pixel wasted space around the main display buffer? you _can_ use that with this...).

N
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

I mixed up the 32byte per entry with 8byte per entry. D'oh. Well you're right, if the GU sees only every 32byte as one single entry, and I have a 16 color 16bit palette, I'm supposed to submit 1 as a parameter. So with my current method I submit twice the entries needed, what isn't a problem because I defined my clut double the size in the first place (by defining unsigned int g_font_clut[16] instead of unsigned short). Should fix that for consistency, even tough it works currently. Thanks :)

So the 4th param is like I supposed it to be. Yet I wonder if it is to be submitted as pixelspace size or bytesize, i.e. with my 4bit texture is it supposed to be 256 (pixelsize) or 128 (bytesize)? It seems to make no difference with my program, but that could just be by coincidence.

BTW: I'd like to get more to know about using the wasted space of the framebuffer if you have any information on that :) My first guess would be to create a pointer to the begin of the waste in the first line and then submit the image with parameters (0,32,BUF_HEIGHT,512, ... )?
Post Reply