mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-06 18:27:20 -05:00
83 lines
1.6 KiB
Go
83 lines
1.6 KiB
Go
|
package Common
|
||
|
|
||
|
type BitMuncher struct {
|
||
|
data []byte
|
||
|
Offset int
|
||
|
BitsRead int
|
||
|
}
|
||
|
|
||
|
func CreateBitMuncher(data []byte, offset int) *BitMuncher {
|
||
|
return &BitMuncher{
|
||
|
data: data,
|
||
|
Offset: offset,
|
||
|
BitsRead: 0,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func CopyBitMuncher(source *BitMuncher) *BitMuncher {
|
||
|
return &BitMuncher{
|
||
|
source.data,
|
||
|
source.Offset,
|
||
|
0,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (v *BitMuncher) GetBit() uint32 {
|
||
|
result := uint32(v.data[v.Offset/8]>>(v.Offset%8)) & 0x01
|
||
|
v.Offset++
|
||
|
v.BitsRead++
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
func (v *BitMuncher) SkipBits(bits int) {
|
||
|
v.Offset += bits
|
||
|
}
|
||
|
|
||
|
func (v *BitMuncher) GetByte() byte {
|
||
|
return byte(v.GetBits(8))
|
||
|
}
|
||
|
|
||
|
func (v *BitMuncher) GetInt32() int32 {
|
||
|
return v.MakeSigned(v.GetBits(32), 32)
|
||
|
}
|
||
|
|
||
|
func (v *BitMuncher) GetUInt32() uint32 {
|
||
|
return v.GetBits(32)
|
||
|
}
|
||
|
|
||
|
func (v *BitMuncher) GetBits(bits int) uint32 {
|
||
|
if bits == 0 {
|
||
|
return 0
|
||
|
}
|
||
|
result := uint32(0)
|
||
|
for i := 0; i < bits; i++ {
|
||
|
result |= v.GetBit() << i
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
func (v *BitMuncher) GetSignedBits(bits int) int {
|
||
|
return int(v.MakeSigned(v.GetBits(bits), bits))
|
||
|
}
|
||
|
|
||
|
func (v *BitMuncher) MakeSigned(value uint32, bits int) int32 {
|
||
|
if bits == 0 {
|
||
|
return 0
|
||
|
}
|
||
|
if bits == 1 { // If its a single bit, a value of 1 is -1 automagically
|
||
|
return -int32(value)
|
||
|
}
|
||
|
// If there is no sign bit, return the value as is
|
||
|
if (value & (1 << (bits - 1))) == 0 {
|
||
|
return int32(value)
|
||
|
}
|
||
|
// We need to extend the signed bit out so that the negative value representation still works with the 2s compliment rule.
|
||
|
result := uint32(4294967295)
|
||
|
for i := byte(0); i < byte(bits); i++ {
|
||
|
if ((value >> i) & 1) == 0 {
|
||
|
result -= uint32(1 << i)
|
||
|
}
|
||
|
}
|
||
|
return int32(result) // Force casting to a signed value
|
||
|
}
|