Playing with bits and bytes in B3D

Blitz3D Forums/Blitz3D Programming/Playing with bits and bytes in B3D

xtremegamr(Posted 2009) [#1]
The title pretty much says it all: I want to change an integer to 4 bytes, and a byte to 8 bits. I also want to combine 8 bits into a byte, and 4 bytes into an integer.

Is this possible in Blitz?


Yasha(Posted 2009) [#2]
Erm... depending upon what you mean by "change", but... the easiest way to do this is probably with the Shr/Shl commands. You take a number of a given size, and Shift it so that its bits don't overlap with those of another number, then simply And the two together. This is how alpha, red, green and blue are combined into a single integer despite being four separate one-byte values:
blue Or (green Shl 8) Or (red Shl 16) Or (alpha Shl 24)

With a little thought you could adapt this to work with numbers made up of any number of bits, including just a single bit if that's practical, working out different amounts to shift left. (EDITED 'cause it was wrong)

In order to extract a value from such an integer requires an extra step: you'd first need to zero all the bits outside the small range you want to extract, using And; so for example, to extract the red value from a four-byte colour:
(colour And $00FF0000) Shr 16

You can also write numeric literals in binary by prefixing them with a % rather than a $ (for hex), if your values don't line up into bytes.


xtremegamr(Posted 2009) [#3]
So if I wanted to combine byte1, byte2, byte3, and byte4 into one integer, I would do this:

byte1 And (byte2 Shl 8) and (byte3 Shl 16) and (byte4 Shl 24)


And then to extract them, I would do this:

byte1= (integer and $FF000000)
byte2= (integer And $00FF00) Shr 8
byte3= (integer And $0000FF00) Shr 16
byte4= (integer And $000000FF) Shr 24


Is that right?


Yasha(Posted 2009) [#4]
All correct, except that you've got the hex values the wrong way around - should be $000000FF for byte1 etc. Otherwise, that's the normal way of doing it, yes. Actually you'd normally write the first (combining) part the other way around, to make that clearer (sorry for the bad example).

To clarify: Shr and Shl literally stand for "shift right" and "shift left" by the specified number of bits. Each character in a hex number is worth four bits, so you can easily envisage the operation you need to perform by looking at the number in hex, which is why $FF000000 needs to be "shifted right" before you can get whatever was "under" the $FF; similarly, it got to that end of the integer by being "shifted left".


Charrua(Posted 2009) [#5]
if you want to play with bits:
a couple of functions, one to Set/Reset and one to test the state of individual bits and an example of use


Print Dec2Bin($FFFFFFFF)
Print Dec2Bin(0)
Number = 65535
Print Number
Print "using Dec2Bin: "+Dec2Bin(Number)
Print "using bin    : "+Bin(Number)

Number = 37	;1000101 bin
Print Number
Print Dec2Bin(Number)
For i=7 To 0 Step -1
	Print "Testing bit: "+i+" : "+TestOnOff(Number,i)
Next

Print Number+" : "+Dec2BinAndBack2Dec(Number)

WaitKey()

Function FlagOnOff(Flags, FlagNumber, State)
	;Flags: 32 bit variable that holds the bits you want to manipulate
	;FlagNumber: bit number to modify (in the range 0..31)
	;State: value to set to the bit indicated by FlagNumber inside Flags
	Mask = 1 Shl FlagNumber
	If State=1 Then
		Return Flags Or Mask
	Else
		Return Flags And ( $FFFFFFFF Xor Mask )
	End If
End Function

Function TestOnOff(Flags, FlagNumber)
	;Flags: 32 bit variable that holds the bit you want to test
	;FlagNumber: number of the bit to test
	;Returns the value of the bit "FlagNumber" inside the "Flags" variable: 0 or 1
	Return (Flags And (1 Shl FlagNumber)) <> 0
End Function

Function Dec2Bin$(number)
	;ok you may call Bin(number) but this function is to test the correct function of TestOnOff function
	a$ = ""
	For i=31 To 0 Step -1
		a = a + Str(TestOnOff(number,i))
		If i Mod 8 = 0 Then a=a+" "
	Next
	Return a
End Function

Function Dec2BinAndBack2Dec(Number)
	Result = 0	;Result start cleared and accumulates a copy of each bit in number
	For i=31 To 0 Step-1
		bitValue = TestOnOff(Number,i)			;test the value of bit i
		Result = FlagOnOff(Result,i,bitValue)	;set or clear that bit in Result
	Next
	Return Result
End Function


Juan


Andy(Posted 2009) [#6]
If you need to manipulate individual bits in a bank, then you can use this.

http://www.blitzbasic.com/codearcs/codearcs.php?code=2405


Charrua(Posted 2009) [#7]
@Andy

hi, the bitWrite (at first saw) in that link if i dont misunderstood, only sets the bit in the right position, ie, if that bit is 0, then if you send a 1 it turn on, but if that bit is 1 in that position and you send a 0, with an OR it will not be cleared. (let me check)

Juan


xtremegamr(Posted 2009) [#8]
Sweet...thanks a lot, guys! This really helped!


Andy(Posted 2009) [#9]
@Charrua

You were right... I just fixed it. Before I originally posted the code, I had cleaned it up and accidently deleted some commented out lines. Sorry!