Sign in to follow this  
ChocoboX

Fuzzy macros

Recommended Posts

ChocoboX    150
Heya people.I'm reading the book "Tricks Of The Window Game Programming Gurus" and I've encountered some macros that I don't understand.I know about alignement of the bits of an RGB value depending on the BPP, but I can't seem to understand those macros.Also I'm having some trouble when it comes to understanding the OR'ing of macros and AND'ing of values.Can somebody cast some light of knowlegde on my mind please ? Thank you ! So here are the evil macros :
[source lang=cpp]
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

Why 0x8000 ? And what does the AND operator exactly do in those cases ?
[source lang=cpp]
#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))

#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))

Hmmmm, I actually don't understand a thing of those macros.What's happening (X_X) ?
[source lang = cpp]
lpdd->SetCooperativeLevel(main_window_handle, 
                                      DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | 
                                      DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))

I understand the function and all and I know each flag must be separated by the OR operator.But why is that ? How does the function know wich flags are being passed in ? What kind of value if the final value after the OR'ing? And sometimes I see things like #define FOO 0x12 Then it gets used as an array index.Something like variable = &array[FOO];

Share this post


Link to post
Share on other sites
Akusei    226
Quote:
Original post by ChocoboX
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)


GetAsyncKeyState returns a SHORT (16 bit integer) that signifies which key was pressed. It also tells you if the key is down by setting the most significant bit to "on" or 1. 0x8000 is hex for the decimal number 32768 which in turn is equal to 100000000000000 in binary. the 1 in this binary number is the bit to test (0x8000). Essentially what this macro is saying is

(Get state for key whatever) : test the state to see if bit 100000000000000 is set. If it is then the key is down, if not then it is not down.

anding to test bits returns a positive number if the bit is on and zero if it is off. I know this may seem confusing, but if you have any more questions, please let me know.

Quote:
Original post by ChocoboX
#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))

#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))


These are little more complicated. basically you are converting three bytes (unsigned chars) into a 16 bit integer and four bytes into a 32 bit integer respectively.

<< means "shift left"... Let me break it down to binary for you:
5 << 5
00000101 << 5 = 10100000

we took 101 and shifted it left 5 times. In relation to the above macros, we want to shift the colors r g and b because we need them in specific bit positions to represent a color. For example:

The 16 bit representation of r = 255 g = 0 b = 255 (purple) is:
rrrrrggggggbbbbb
1111100000011111

anding the color values converts them into their proper bit lengths and shifting them "packs" them into the correct position. The same goes for the second macro as well, only for 32 bits instead of 16. Again, any questions, please ask.

Quote:
Original post by ChocoboX
lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))


These are called "Flags" and they are cumulative, meaning you can keep oring them together and they will not lose their original value.

Basically you are taking many numbers and ORing then together to make one big number. Again, this is bitwise stuff. Here are some more examples.


Flag1 = 2
Flag2 = 4
Flag3 = 8
Flag4 = 16

DWORD flags = Flag1 | Flag2 | Flag4



Now I have a DWORD with the value 22. Now if I want to "test" and see if I have certain flags set, I simply AND my 22 by the individual flags, like so.


if ((flags & Flag1) == Flag1)
//Do Something because we have Flag1 set

if ((flags & Flag2) == Flag2)
//Do Something because we have Flag2 set



if 22 & 2 = 2 then the flag is set... if 22 & 2 = 0 then it is not. this holds true for all flags; 22 & 8 = 0 but 22 & 6 = 6.

NOTE: The flags must be numbered properly. Notice that my flags are 2, 4, 8 and 16... if they were 2, 4, 6, 8 then the flags would not work properly.


I hope all of this helps... and once again, please ask if you are confused or have any other questions.

Share this post


Link to post
Share on other sites
ChocoboX    150
Such a kind person ! Thank you very very much ! ^-^ It is much more clear now.

Can't we do (r&31) + (g&31) + (b&31)? Without shifting ?
I still do not understand the use of the AND-ing with 31.

Share this post


Link to post
Share on other sites
Zahlman    1682
Addition will work in this case because of how the fields are aligned, but it actually kind of obfuscates things - the idea is that we're doing bitwise manipulation, so tossing an arithmetic operator in there just makes it more confusing. The and/shift/or idiom is something commonly recognized by maintenance programmers.

The ANDs in this case are clearing the high bits of the input values so that they don't interfere:

IN: 00000000 10101010 01010101
AND 00011111 00111111 00011111
-------------------------------
00000 101010 10101


And then the shifting and ORing puts those together in order, '0000010101010101'. Without the AND, this happens:


IN: 00000000 10101010 01010101
SHIFTED:
RED 00000000
GREEN 10101010
BLUE 01010101


Now the bottom 16 bits are '0001010101010101'. The un-cleared blue bits happened to match up with the green bits they overlapped, but the green changed the red value, and that's bad. Worse, if high bits had been set in the input red value, we would overflow a 16-bit value, which could cause problems later (say we had to pass it in a 32-bit variable but had to be within range for whatever colour-handling library we're using; that might signal an assertion, or if we're really unlucky, crash the program).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this