Forum > Tutorials
[TUTORIAL] Bitmasking
(1/1)
Mjollna:
Hello :)
First post... It took me some time to get out of silence :) I'll just introduce myself a little... I'm 29, and I play Wow for almost five years now. I started to be interested about things "around" the game through exploration one year ago. All this led me to look closer at the files, and finally I ended up here :) What I like in modding/world building/looking at files with an hex editor is to learn new things, and contrary to the original game, the whole creative process attached to it. Even though I ended university with one year of computer science, I studied social sciences as major. That's why most of my knowledge in this field is self-learning (thx Google). I can make (very ?) ugly but functional scripts, and I don't mind spending a lot of time trying to understand a notion if in the end I can create something out of it.
I have to say I admire all your work a lot, programs, maps, tutorials, custom models... That's one of the reasons I decided to register here, and also why it takes me so long to say something :)
As I said, I started looking at the files very recently. Since the end of July I've mostly tried to understand the differences between 3.x and 4.x adt, so I have very basic knowledge of other Wow formats. A few weeks ago a friend of mine wrote a tutorial for me about bitmasking, which helped me understanding how flags work in Wow files. I saw this morning a thread about bitmasking, so I thought I'd share the tutorial here (I hope it's the right place to post). Of course, my friend is ok for translation/repost, I asked him, and he even re-read the translated version (also thx to Pag for 2nd re-reading).
Thanks for reading, hope the post will be useful :)
------------------------------------------------------------- Bitmasking
- Original author : Hâthor. - Translation (French -> English) & last example : Mjollnà.
Introduction
I'm (Hâthor) going to choose enum in C# as an example. It's like a special table, declared as such :
--- Code: ---public enum DayOfWeek { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } --- End code ---
It can be used this way in the code :
--- Code: ---private DayOfWeek day = DayOfWeek.Monday; --- End code ---
The value given by the compiler is 0 for the first one, and adds 1 for every following entry. Of course, it's possible to declare such tables.
Flags
The same enum with flags works like this :
--- Code: ---public enum DayOfWeek { Monday = 1, Tuesday = 2, Wednesday = 4, Thursday = 8, Friday = 16, Saturday = 32, Sunday = 64 } --- End code ---
What's interesting here is that the combination of values is easier than above. For example, if we want to write Monday and Thursday in our variable day, we'll write :
--- Code: ---private DayOfWeek day = DayOfWeek.Monday | DayOfWeek.Thursday; --- End code ---
The "|" is the logical operator XOR.
--- Code: ---1 => 00000001 XOR 8 => 00001000 ------------- 9 => 00001001 --- End code ---
And 9 is 8 + 1 (Monday + Thursday) ! 10 would be Tuesday + Thursday, etc. All combinations take only one int (= 4 bytes). It takes less space than a whole table of values.
Mask
How can I know if my variable (9) contains Thursday (8) ? We'll apply a mask, which is going to hide all the things we don't want to see. We mask the total value with an AND that holds the value we want to find :
--- Code: ---9 => 00001001 // Monday + Thursday : total value AND 8 => 00001000 // Thursday : what we're looking for ------------- 8 => 00001000 // Thursday remains --- End code ---
By applying the mask, we found the value we wanted, 8 / Thursday. Then the variable containing Thursday can be written this way :
--- Code: ---if ((day & DayOfTheWeek.Thursday) == DayOfTheWeek.Thursday) { ... } --- End code ---
Another example with 17, does it contain thursday ? :
--- Code: ---17 => 00010001 // Friday and Monday AND 08 => 00001000 // Thursday -------------- 00 => 00000000 --- End code ---
0 is different from 8, so it doesn't contain Thursday.
Another example : netmask and subnet
An IPv4 address is divided in 2 parts, the host and the network. Usually, personal routers give an IP that looks like 192.168.1.xxx, and the mask 255.255.255.0. Let's say the PC is host number 2 (so that the IP becomes 192.168.1.2). When data runs accross a network, both host and network often need to be known separately. That's why routers apply the netmask to the IP to know where to send packets.
For example :
--- Code: ---192.168.1.2 => 11000000.10101000.00000001.00000010 AND 255.255.255.0 => 11111111.11111111.11111111.00000000 ---------------------------------------------------- 192.168.1.0 => 11000000.10101000.00000001.00000000 --- End code ---
My data has to be sent to network 192.168.1.0. If the mask is inverted, it's possible to know the host.
Another example : wdt flags
It works exactly the same way. On one byte, all the flags are "summed up", and you can find them by looking at the binary.
Example : If you have the value 0x6E (see screenshot below, click to see bigger image), if you convert it in binary, you get this result : 0110 1110 (for quick conversion : http://home2.paulschou.net/tools/xlate/) Every "1" if an activated flag.
The schema below converts every value in hex and decimal.
Here we have : 10 : 0x2 100 : 0x4 1000 : 0x8 10 0000 : 0x20 100 0000 : 0x40
Let's add them again in hex : 0x40 + 0x20 + 0x8 + 0x4 + 0x2 = 0x6E, it's ok.
Every flag adds a special feature to the way adt are handled/displayed by the wdt : http://www.pxr.dk/wowdev/wiki/index.php?title=WDT
mferrill:
Very nice! Glad you decided to register, and get out of the silence! :D I'm sure this will be very helpful to a lot of people. Not just as a nice reference, but the detailed explanations should help most actually learn a little :D
Steff:
Posted: Mon Aug 22, 2011 8:43 pm
Its 2 years old ! But still usefull ;)
Navigation
[0] Message Index
|