www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Bits in Int / short / etc

reply Nate <plummn comdel.net> writes:
Hello Folks,

I'm having a real tough time trying to figure out how to accomplish 
this. What I am doing is reading a game map file; the format is a series 
of chars in the header and then compressed "WORDS" (ushorts) in the body.

I've figured out how to read the entire header and I have figured out 
how to decompress the compressed map portioin of "WORDS". The problem is 
that some of these ushorts need further breaking down by finding 
'highest bits' and such and I have no idea how to proceed...

Here is an example of the data. 280 is an empty tile 33024-33026 are 4 
seperate animated tiles. That data needs broken down further.

33024 33025 280 280 [ A TON MORE 280's (256 wide total)] 280
33026 33027 280 280 [ A TON MORE 280's (256 wide total)] 280

33024 is supposed to be animation 0 with offset 0
33025 is supposed to be animation 1 with offset 0
33026 is supposed to be animation 2 with offset 0
33027 is supposed to be animation 3 with offset 0

How do I get the highest bit for 33024, etc and then the lower 15 bits 
if it is zero? If its not zero i need bits 8-14... I'm very lost at this 
point. How the heck can I do this?

Here is the only info I have on the file:

 When you decompress the data, you'll have a 256x256 array of WORDs...
 Each one of these can represent a single tile that maps over to the 

 in tiles.bmp or it can point to an animation.  Look at the highest bit of
 each word, if it is 0, the lower 15 bits are an index to a tile in
 tiles.bmp (40 tiles per row since each tile is 16x16).  Otherwise: If bit
 15 is 1, the lower 15 bits refer to an animation... but an animation can
 have an "offset".. so if you had an animation that was 10 frames 

 could put two of them next to each other, one with an offset of 0 

 and one with an offset of 5, so the animations would appear out of phase.
 The lower 8 bits of the WORD represent the animation number (since there
 can be 256 animations) and bits 8-14 is the animation offset.

Thanks very much for your help guys, Nate
May 29 2005
next sibling parent reply Nate <plummn comdel.net> writes:
I've figured how to do this by hand, I'm still not sure how to do this 
with D.

Examples
33024 is 1000 0001 00000000 (animation 0, frame 1)

** 1000 = 1 (3 zeros ignored)
** 0001 = offset by 1 (first anim frame)
** 00000000 = tile zero

33280 is 1000 0010 00000000 (animation 0 frame 2)
33536 is 1000 0011 00000000 (animation 0 frame 3)

32793 is 1000 0000 00011001 (animation 25 frame 1)
33305 is 1000 0010 00011001 (animation 25 frame 2)
33561 is 1000 0011 00011001 (animation 25 frame 3)
(11001 is 25 in binary)

So how can I convert an integer to binary and then slice up the binary 
into sections like this and convert them back to int?

Again thanks for your time.

Nate wrote:
 Hello Folks,
 
 I'm having a real tough time trying to figure out how to accomplish 
 this. What I am doing is reading a game map file; the format is a series 
 of chars in the header and then compressed "WORDS" (ushorts) in the body.
 
 I've figured out how to read the entire header and I have figured out 
 how to decompress the compressed map portioin of "WORDS". The problem is 
 that some of these ushorts need further breaking down by finding 
 'highest bits' and such and I have no idea how to proceed...
 
 Here is an example of the data. 280 is an empty tile 33024-33026 are 4 
 seperate animated tiles. That data needs broken down further.
 
 33024 33025 280 280 [ A TON MORE 280's (256 wide total)] 280
 33026 33027 280 280 [ A TON MORE 280's (256 wide total)] 280
 
 33024 is supposed to be animation 0 with offset 0
 33025 is supposed to be animation 1 with offset 0
 33026 is supposed to be animation 2 with offset 0
 33027 is supposed to be animation 3 with offset 0
 
 How do I get the highest bit for 33024, etc and then the lower 15 bits 
 if it is zero? If its not zero i need bits 8-14... I'm very lost at this 
 point. How the heck can I do this?
 
 Here is the only info I have on the file:
 
  > When you decompress the data, you'll have a 256x256 array of WORDs...
  > Each one of these can represent a single tile that maps over to the 
 pieces
  > in tiles.bmp or it can point to an animation.  Look at the highest 
 bit of
  > each word, if it is 0, the lower 15 bits are an index to a tile in
  > tiles.bmp (40 tiles per row since each tile is 16x16).  Otherwise: If 
 bit
  > 15 is 1, the lower 15 bits refer to an animation... but an animation can
  > have an "offset".. so if you had an animation that was 10 frames 
 long, you
  > could put two of them next to each other, one with an offset of 0 
 (normal)
  > and one with an offset of 5, so the animations would appear out of 
 phase.
  > The lower 8 bits of the WORD represent the animation number (since there
  > can be 256 animations) and bits 8-14 is the animation offset.
 
 Thanks very much for your help guys,
 
 Nate

May 29 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
Here is an alternative, kinda fun, and maybe educational solution to the  
problem:

import std.stdio;

void main() {
	int frame,anim;
	
	parseAnimFrame(33280,anim,frame);
	writefln("33280:= anim=%02d, frame=%02d",anim,frame);
	
	parseAnimFrame(33536,anim,frame);
	writefln("33536:= anim=%02d, frame=%02d",anim,frame);
	
	parseAnimFrame(32793,anim,frame);
	writefln("32793:= anim=%02d, frame=%02d",anim,frame);
	
	parseAnimFrame(33305,anim,frame);
	writefln("33305:= anim=%02d, frame=%02d",anim,frame);
	
	parseAnimFrame(33561,anim,frame);
	writefln("33561:= anim=%02d, frame=%02d",anim,frame);
}

void parseAnimFrame(int raw, out int anim, out int frame)
{
	bit[] bVal = (cast(bit*)&raw)[0..32];
	anim = bitArrayToInt(bVal[0..8]);
	frame = bitArrayToInt(bVal[8..12]);
}

int bitArrayToInt(bit[] array)
{
	int val;
	foreach(bit b; array.reverse) {
		val *= 2;
		val += b;
	}
	return val;
}

Of course, it's less efficient than Tom's. However, it does show casting  
to a bit[] (which can be useful) and how to then reconstitute that bit[]  
into an int.

Regan

On Sun, 29 May 2005 18:19:00 -0400, Nate <plummn comdel.net> wrote:
 I've figured how to do this by hand, I'm still not sure how to do this  
 with D.

 Examples
 33024 is 1000 0001 00000000 (animation 0, frame 1)

 ** 1000 = 1 (3 zeros ignored)
 ** 0001 = offset by 1 (first anim frame)
 ** 00000000 = tile zero

 33280 is 1000 0010 00000000 (animation 0 frame 2)
 33536 is 1000 0011 00000000 (animation 0 frame 3)

 32793 is 1000 0000 00011001 (animation 25 frame 1)
 33305 is 1000 0010 00011001 (animation 25 frame 2)
 33561 is 1000 0011 00011001 (animation 25 frame 3)
 (11001 is 25 in binary)

 So how can I convert an integer to binary and then slice up the binary  
 into sections like this and convert them back to int?

 Again thanks for your time.

 Nate wrote:
 Hello Folks,
  I'm having a real tough time trying to figure out how to accomplish  
 this. What I am doing is reading a game map file; the format is a  
 series of chars in the header and then compressed "WORDS" (ushorts) in  
 the body.
  I've figured out how to read the entire header and I have figured out  
 how to decompress the compressed map portioin of "WORDS". The problem  
 is that some of these ushorts need further breaking down by finding  
 'highest bits' and such and I have no idea how to proceed...
  Here is an example of the data. 280 is an empty tile 33024-33026 are 4  
 seperate animated tiles. That data needs broken down further.
  33024 33025 280 280 [ A TON MORE 280's (256 wide total)] 280
 33026 33027 280 280 [ A TON MORE 280's (256 wide total)] 280
  33024 is supposed to be animation 0 with offset 0
 33025 is supposed to be animation 1 with offset 0
 33026 is supposed to be animation 2 with offset 0
 33027 is supposed to be animation 3 with offset 0
  How do I get the highest bit for 33024, etc and then the lower 15 bits  
 if it is zero? If its not zero i need bits 8-14... I'm very lost at  
 this point. How the heck can I do this?
  Here is the only info I have on the file:
   > When you decompress the data, you'll have a 256x256 array of  
 WORDs...
  > Each one of these can represent a single tile that maps over to the  
 pieces
  > in tiles.bmp or it can point to an animation.  Look at the highest  
 bit of
  > each word, if it is 0, the lower 15 bits are an index to a tile in
  > tiles.bmp (40 tiles per row since each tile is 16x16).  Otherwise:  
 If bit
  > 15 is 1, the lower 15 bits refer to an animation... but an animation  
 can
  > have an "offset".. so if you had an animation that was 10 frames  
 long, you
  > could put two of them next to each other, one with an offset of 0  
 (normal)
  > and one with an offset of 5, so the animations would appear out of  
 phase.
  > The lower 8 bits of the WORD represent the animation number (since  
 there
  > can be 256 animations) and bits 8-14 is the animation offset.
  Thanks very much for your help guys,
  Nate


May 29 2005
parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Regan Heath wrote:
 Here is an alternative, kinda fun, and maybe educational solution to 
 the  problem:
 
 // snip ...
 
 int bitArrayToInt(bit[] array)
 {
     int val;
     foreach(bit b; array.reverse) {
         val *= 2;
         val += b;
     }
     return val;
 }
 
 Of course, it's less efficient than Tom's. However, it does show 
 casting  to a bit[] (which can be useful) and how to then reconstitute 
 that bit[]  into an int.

What about this code ? :D I'm sure it can be done more efficient too... # int bitArrayToInt(bit[] array) # { # static bit[int.sizeof * 8] tmp; # tmp[0 .. array.length] = array[]; # tmp[array.length .. length] = 0; # return *cast(int*)&tmp[0]; # } -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 30 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 30 May 2005 14:50:13 +0200, Tom S  
<h3r3tic remove.mat.uni.torun.pl> wrote:
 Regan Heath wrote:
 Here is an alternative, kinda fun, and maybe educational solution to  
 the  problem:
  // snip ...
  int bitArrayToInt(bit[] array)
 {
     int val;
     foreach(bit b; array.reverse) {
         val *= 2;
         val += b;
     }
     return val;
 }
  Of course, it's less efficient than Tom's. However, it does show  
 casting  to a bit[] (which can be useful) and how to then reconstitute  
 that bit[]  into an int.

What about this code ? :D I'm sure it can be done more efficient too... # int bitArrayToInt(bit[] array) # { # static bit[int.sizeof * 8] tmp; # tmp[0 .. array.length] = array[]; # tmp[array.length .. length] = 0; # return *cast(int*)&tmp[0]; # }

I'd prefer... int bitArrayToInt(bit[] array) { bit[] tmp; if (array.length >= 32) tmp = array; else { tmp.length = 32; tmp[0 .. array.length] = array[]; tmp[array.length .. tmp.length] = 0; } return *(cast(int*)tmp.ptr); } Of course, if you used int.sizeof you could make a generic one using templates. Regan
May 30 2005
prev sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
ushort value;

if (value & 0x8000) {
	ushort tileIndex = value & 0x7fff;
	// read tiles.bmp
} else {
	ushort animationNbr = value & 0xff;
	ushort animationOffst = (value & 0x7fff) >> 8;
	// load the animation
}


Nate wrote:
 33024 is supposed to be animation 0 with offset 0
 33025 is supposed to be animation 1 with offset 0
 33026 is supposed to be animation 2 with offset 0
 33027 is supposed to be animation 3 with offset 0

According to my calculations: 33024 - animation 0; offset 1 33025 - animation 1; offset 1 33026 - animation 2; offset 1 33027 - animation 3; offset 1 -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 29 2005
parent reply Nate <plummn comdel.net> writes:
Amazing! I am _very_ grateful. Coming from a VB -> C# background I am 
weak in this area. This works perfect but I don't understand how, if you 
  know any good references for this I'd love to read them.

Thanks again.

Tom S wrote:
 ushort value;
 
 if (value & 0x8000) {
     ushort tileIndex = value & 0x7fff;
     // read tiles.bmp
 } else {
     ushort animationNbr = value & 0xff;
     ushort animationOffst = (value & 0x7fff) >> 8;
     // load the animation
 }
 
 
 Nate wrote:
 
 33024 is supposed to be animation 0 with offset 0
 33025 is supposed to be animation 1 with offset 0
 33026 is supposed to be animation 2 with offset 0
 33027 is supposed to be animation 3 with offset 0

According to my calculations: 33024 - animation 0; offset 1 33025 - animation 1; offset 1 33026 - animation 2; offset 1 33027 - animation 3; offset 1

May 29 2005
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Nate wrote:
 Amazing! I am _very_ grateful. Coming from a VB -> C# background I am 
 weak in this area. This works perfect but I don't understand how, if you 
  know any good references for this I'd love to read them.

Maybe this one: http://www.gamedev.net/reference/articles/article1563.asp -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 29 2005