Read & Assign specific bits in a byte
BlitzMax Forums/BlitzMax Programming/Read & Assign specific bits in a byte
| ||
I have pursued for hours working functions to read & write bits to a single byte. I need a function that can retreive a value from any number of bits from the byte, so I wrote this: Function GetBits:Int(num:Int,start:Byte,length:Byte=1,isbyte:Byte=1) Local ret:Int=0,pos:Byte,pos2:Byte=0 If isbyte=True Then start=start+23 For pos=start+1 To start+length+1 ret=ret+Int(Mid(Bin$(num),pos,1))*(2^(length-pos2)) pos2=pos2+1 Next Return ret End Function I needed to set the value of an individual bit in a byte, so I made this: Function SetBit:Byte(byt:Byte,pos:Byte,tobit:Byte) Local ret:Byte=0 For Local modret:Byte=0 To 7 If modret<>pos Then ret:+ (2^modret)*Int(Mid(Right(Bin(byt),8),modret+1,1)) ElseIf tobit=1 ret:+ (2^modret) EndIf Next Return ret End Function And they don't seem to work. I don't exactly care if they write bits backwards or something, but it is mandatory that when I set a bit to a byte, when I try to read the same position, I get what I wrote. And don't go telling me bytes for everything isn't that much worse; I'm writing an engine that requires miniscule amounts of information requiring only a few bits each, but there's far too many of these little bits to waste space. I don't know what I'm doing wrong, but it is become very upsetting. Please help, and thanks in advance. |
| ||
Small example :SuperStrict Local b:Byte = $00 Print Bin(b) b :| $04 ' set the 3rd bit Print Bin(b) ' shifts are 0 indexed ... b :| 1 Shl 0 ' set the 1st bit Print Bin(b) b :| 1 Shl 4 ' set the 5th bit Print Bin(b) b :~ 1 Shl 4 ' toggle the 5th bit off Print Bin(b) b :~ 1 Shl 4 ' toggle the 5th bit on Print Bin(b) ' reading bits ' is 5th bit set? Print b & $10 ' > 0 is true b :~ 1 Shl 4 ' toggle the 5th bit off Print b & $10 ' and with shifting Print b & 1 Shl 4 ' = 0 is false b :~ 1 Shl 4 ' toggle the 5th bit on Print b & 1 Shl 4 Don't mind the long results from Bin(), it shows 32-bits with of bits by default. |
| ||
Thanks, but I'm looking for something along the lines of functions. |
| ||
What, you mean like this?Strict Import Brl.Retro Function SetBit(in:Int, position:Int) Return (in|(%1 Shl (position-1))) End Function Function UnsetBit(in:Int, position:Int) Return (in&(~(%1 Shl (position-1)))) End Function Function BitRange:Int(in:Int, start:Int, length:Int) in :Shr start in :& $FFFFFFFF Shr length Return in End Function Local bitbot:Byte = 0 bitbot = SetBit(bitbot,1) bitbot = SetBit(bitbot,8) Print Bin(bitbot)[24..] bitbot = $FF bitbot = UnsetBit(bitbot, 1) bitbot = UnsetBit(bitbot, 8) Print Bin(bitbot)[24..] SeedRnd(Millisecs()) Local random:Int = Rand(-1000000, 1000000) Print "Bin(random) = "+Bin(random) Print "Bin(random)[12..20] = "+Bin(random)[12..20] Print Bin(BitRange(random, 12, 8))[24..] I just wonder if you'll understand how these work, considering you spent a bunch of time, for some reason, trying to do this with strings... |
| ||
I was using strings because I first tried bit shifting and couldn't get that to work the way I wanted, either. And thanks very much, these functions should do the trick. |
| ||
Oi, I've got one more problem. (I renamed BitRange to GetBits for the sake of convenience) why does this line of code: GetBits(PeekByte(tile.bank,fx),bitpos*2,2) return 22, when PeekByte(tile.bank,fx) is 22 and bitpos is 0? EDIT: After further investigation, it seems the function's length is somehow automatically equal to 8 - start.. AUGH all this bitshifting is beyond me |
| ||
That one there's a brainfart.Function BitRange:Int(in:Int, start:Int, length:Int) Return ((in Shr start) & (~($FFFFFFFF Shl length))) End Function |
| ||
thanks much, works like a charm. |