• ### Announcements

#### Archived

This topic is now archived and is closed to further replies.

# More DX 16bit queries ... ;)

## 18 posts in this topic

Take a look at my homepage......in the article

32,24,16 and 8 bit.....that should explain it all........at least,.....most of it.

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm

0

##### Share on other sites
Depending on application, one way you could do this is by creating an index of 0-255 values for Red, Green and Blue. I do this like so:

unsigned short rgb_index[256][3];

Then fill the structure with colour information. The first array index points to the colour amount, the second to the colour itself (R G or B, I use R = 0 G = 1 B = 2, but you could change that if you wanted to). Now, when you want to get a finished colour, you simply say:

color = rgb_index[r_color][0] | rgb_index[g_color][1] | rgb_index[b_color][2];

As I said, there will be situations where you won't want to use this because of the way it works. However, it is one way of doing things that you might want to take a look at.

Good luck

Starfall

0

##### Share on other sites
Thanks a lot to you both - You've been a lot of help.

Thanks again,

James

0

##### Share on other sites
Starfall......You should've explained it further how to make the LUT.

Look at

code:
DWORD* Create16bppLUT(DWORD bitMask){DWORD * p_lut = new DWORD[256];if (p_lut == NULL) return NULL;for (__int64 i = 0; i < 256; i++){p_lut[i] = DWORD((( i * __int64(bitMask)) / 255) & bitMask);}return p_lut;}

And call this function like:

DWORD *Red;

after that you can use what you said

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm

0

##### Share on other sites
Hi Cj,

Thanks for the extra code... a couple of things I don't get however Could you explain why you use '__int64' variable type (not sure what this is exactly). Also, why do you malloc the memory at runtime, is this faster than using a play array of say:
WORD r_LUT[256];
?

Anyway, thanks for your help,

James

0

##### Share on other sites
Okay......well.....i use an __int64 for 2 reasons, reason 1 is to have it working on different systems, since an int can be different on every computer. Reason 2 is because of the DWORD the function receives. A DWORD is a 32 bit unsigned integer. So...the values will range exactly the same as __int64. Makes sense? to me it does......I might've been wrong though. Haven't tried it different yet.

And about the memory allocation on run-time. I always do that. It's kinda my behavior. And I find it easier to use a pointer to something instead......

More questions?

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm

0

##### Share on other sites
And I find it easier to use a pointer to something instead......

Come again? How's an array like he suggested any different? It's still a pointer, just preallocated for you. In fact, for all intents and purposes exactly the same as using malloc, but with less hassle. I find it far easier to allocate fixed size memory like that, anyway.

Regards

Starfall

0

##### Share on other sites
Above where CJ used a __int64 thats a no-no. The problem is that an int64 is a microsoft specific way to hold a 64 bit integer.... which is completely unnecessary when we deal with 16 bit colors (and probably slow too since intel machines are 32 bit.) Also, I'm not sure that the array produced would be what you desire, although I haven't looked into that very much.
0

##### Share on other sites
To clear some things up. First, your best bet is to use an int, not an __int64. Like someone previously noted, __int64's are a no-no. Definately not ANSI C++ standard. For large integers, an int/long is absolutely fine. However, in this case, if memory serves form looking at that code, our values are ranging from 0 to 255. Use a char.
Second thing...this:

int MyArray[256];

and this:

int *MyArray = (int *)malloc(256 * sizeof(int));
OR
int *MyArray = new int[256];

The last two do exactly the same thing. They are just different versions of each other. However, a pre-allocated array only uses the stack to store the array. Once it's out of scope, the array no longer exists. Using malloc() or new dynamically allocates it, and the memory is available until you call free() or delete[]. Therefore, they are not the same thing.

0

##### Share on other sites
Everybody has another style of coding, and after examining what you said. I agree......

I will always use new and delete functions. Everybody his liking. And......you are right about the __int64 thingy.....just an int works just fine too...........

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm

0

##### Share on other sites
Hey,

Thanks for all your replies guys, most useful

Have just been looking on directxfaq.com, and found this article; http://www.directxfaq.com/kbase/ddraw/16bitspixels.htm

The code in it looks pretty similar to CJs
Infact, I'd say identical heh.

Anyway, thanks a lot,

James

0

##### Share on other sites
I think you missed my point, Coder++. Using a global array is, in this case, much the same as using a pointer to memory allocated at startup and deallocated at shutdown. As CJ says, everyone has their style, and that is the style I find most simple to use for such things.

Also, using a char in this code would not be such a good idea. Even an unsigned char would still overflow when incremented at 255, and thus the for loop would not catch it.

My advice is to not bother to be frugal about counter variables and such. You're far more likely to cause more trouble than you save.

Regards

Starfall

0

##### Share on other sites
jAMES,
hat's right, it's the place where I got it from a long time ago, I lost the url though. I've been using it for quite a while, but i changed to 24 bit these days. I got a good understanding about 16 bit, and will probably soon write a better thing.

I'm just wondering, what would be faster? To shift? or to use a LUT.....what's more important? speed or memory? I would say a LUT is still faster........

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm

0

##### Share on other sites
James -
An easy way is similar to using Starfalls-
just create an array that converts from 555 to the screen format and one that converts back:

unsigned short clr_555_to_fmt[32768];
unsigned short clr_fmt_to_555[65536];

All colors would pass through the first array before displaying them, and if you need to read information back, pass them through the 2nd.

The reason they are different sizes is the first only takes a 555 amount, and the second possibly uses 565.

If this doesn't make much sense, let me know and I'll type something better -- I'm at work right now.

Now, about using malloc and static arrays:
it doesn't really matter. It's just coding style. It some cases though, using a static array will bloat the .exe file.

As for using int and such, you have to remember that int is not a fixed size - it will vary from machine to machine and depending on the compiler.

Use short for 16 bit, and long for 32 bit
(on a x86 machine at least).

Jim

0

##### Share on other sites
Hi Jim,

Thanks for your reply, I *think* I get you, but could you kindly exemplify the creation of the LUT a little?

I'd appreciate it

Thanks,
James

btw, Lightbefallen is looking amazing!

0

##### Share on other sites
James-

Here's what I do: All my tiles are stored in a 555 format, just because I definately know that's what it is. All color calculations performed are 555 no matter what.

When it comes time, say to load a tile into the cache, it will pass through a conversion function to convert to the screen format.

So, let's say we have a 32x32 tile stored at 555 format and this is my loading function:

for(i=0;i<32;i++) {
fread(&buf, 1, 32*2, fp);
for(j=0;j<32;j++)
buf[j] = clr_555_to_fmt[buf[j]];
buf += page.lpitch;
}

I never have to worry what the screen format is. Let's assume I'm reading a pixel from a screen buffer or tile buffer or whatever to work on:

color = page.ptr[12];
color555 = clr_fmt_to_555[color];

Then I do color conversions based on 555 format to color555 variable, then I can write it back:

page.ptr[12] = clr_555_to_fmt[color555];

Now, to setup the conversion tables, just do this:

unsigned short clr_555_to_fmt[32768];
unsigned short clr_fmt_to_555[65536];

for(i=0;i<65536;i++) {
// convert 555 to format
if(i < 32768) {
red = (i >> 10) & 31;
green = (i >> 5) & 31;
blue = i & 31;
clr_555_to_fmt[i] = (red << 11) | (green << 5) | blue;
}

// convert format to 555 - assume 565
red = (i >> 11) & 31;
green = (i >> 5) & 31;
blue = i & 31;
clr_fmt_to_555[i] = (red << 10) | (green << 5) | blue;
}

Please excuse me if this is a little off - I'm trying to do this from memory, but it looks right. You should get the idea.

Just create a better one that shifts and arranges the colors based on the info you get from GetSurfDesc.

Thanks about TLB. It's being totally revamped - we have a new graphics and sound engine, plus some awesome stuff going in - we hope to have a new demo in the next couple of months.

0

##### Share on other sites
As already mentioned there is no reason to use an _int64 for creating portable apps, 'cause it's MS specific. And I don't think it's reasonable to talk about portability when writing apps for DirectX. I'd really like to see a port of DirectX to a system that does not use the same size for an int.

CU,
Alex

------------------
Alexander Stockinger
Programmer

0

##### Share on other sites
Hi =)

After reading through a few articles on the problems of 16bit RGB formats on vid cards, I've finally (almost) got it licked.

What I'm not sure on is how to actually implement the different variations in my code. I can detect the format etc., that isn't the problem... Hmm, this is hard to explain.

What I mean is, say I have a 5-5-5 graphics card. Pure white will therefore me (31,31,31). But say I then use the code on a 5-6-5 format graphics card... It'll be a pinky colour. Basically what I'm asking is, do I pick say 5-6-5 as my primary format (65k colours) and then reduce (ie. divide by 2 the green componet) for a 5-5-5 card etc.?

Also, is it better to (at each point in my code where I want to draw a pixel say) have an if() or switch() kinda thing or should I use a macro which encompasses everything (but has a lot of shifts...)?

I'm sorry if I haven't made sense... basically I know how to detect the format, the shifts needed etc, just not how to implement them (in an optimized way).

Any help would be appreciated

Thanks,
James

0

##### Share on other sites
Regarding ints and DX - do you know what size an int is on the dreamcast? Is it use 32 or 64 bit registers?

As far as porting, you can alway generalize function calls and use DX in those. When you port, simply change a couple routines and it's done.

Jim

0