mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-01-14 05:16:43 -05:00
Decouple bitmuncher (#495)
* adding comments to d2interface for linter * moved d2render renderer interfaces and types into d2interface * fixed most lint errors for monstats loader * decouple bitmuncher to interface
This commit is contained in:
parent
06202a2ddf
commit
691368cba7
@ -1,66 +1,117 @@
|
||||
package d2common
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
// BitMuncher is used for parsing files that are not byte-aligned such as the DCC files.
|
||||
type BitMuncher struct {
|
||||
data []byte
|
||||
Offset int
|
||||
BitsRead int
|
||||
offset int
|
||||
bitsRead int
|
||||
}
|
||||
|
||||
func CreateBitMuncher(data []byte, offset int) *BitMuncher {
|
||||
return &BitMuncher{
|
||||
data: data,
|
||||
Offset: offset,
|
||||
BitsRead: 0,
|
||||
}
|
||||
const (
|
||||
twosComplimentNegativeOne = 4294967295
|
||||
byteLen = 8
|
||||
oneBit = 0x01
|
||||
fourBytes = byteLen * 4
|
||||
)
|
||||
|
||||
// CreateBitMuncher Creates a BitMuncher
|
||||
func CreateBitMuncher(data []byte, offset int) d2interface.BitMuncher {
|
||||
return (&BitMuncher{}).Init(data, offset)
|
||||
}
|
||||
|
||||
func CopyBitMuncher(source *BitMuncher) *BitMuncher {
|
||||
return &BitMuncher{
|
||||
source.data,
|
||||
source.Offset,
|
||||
0,
|
||||
}
|
||||
// CopyBitMuncher Creates a copy of the source BitMuncher
|
||||
func CopyBitMuncher(source d2interface.BitMuncher) d2interface.BitMuncher {
|
||||
return source.Copy()
|
||||
}
|
||||
|
||||
// Init initializes the BitMuncher with data and an offset
|
||||
func (v *BitMuncher) Init(data []byte, offset int) d2interface.BitMuncher {
|
||||
v.data = data
|
||||
v.offset = offset
|
||||
v.bitsRead = 0
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// Copy returns a copy of a BitMuncher
|
||||
func (v BitMuncher) Copy() d2interface.BitMuncher {
|
||||
v.bitsRead = 0
|
||||
return &v
|
||||
}
|
||||
|
||||
// Offset returns the offset of the BitMuncher
|
||||
func (v *BitMuncher) Offset() int {
|
||||
return v.offset
|
||||
}
|
||||
|
||||
// SetOffset sets the offset of the BitMuncher
|
||||
func (v *BitMuncher) SetOffset(n int) {
|
||||
v.offset = n
|
||||
}
|
||||
|
||||
// BitsRead returns the number of bits the BitMuncher has read
|
||||
func (v *BitMuncher) BitsRead() int {
|
||||
return v.bitsRead
|
||||
}
|
||||
|
||||
// SetBitsRead sets the number of bits the BitMuncher has read
|
||||
func (v *BitMuncher) SetBitsRead(n int) {
|
||||
v.bitsRead = n
|
||||
}
|
||||
|
||||
// GetBit reads a bit and returns it as uint32
|
||||
func (v *BitMuncher) GetBit() uint32 {
|
||||
result := uint32(v.data[v.Offset/8]>>uint(v.Offset%8)) & 0x01
|
||||
v.Offset++
|
||||
v.BitsRead++
|
||||
result := uint32(v.data[v.offset/byteLen]>>uint(v.offset%byteLen)) & oneBit
|
||||
v.offset++
|
||||
v.bitsRead++
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// SkipBits skips bits, incrementing the offset and bits read
|
||||
func (v *BitMuncher) SkipBits(bits int) {
|
||||
v.Offset += bits
|
||||
v.BitsRead += bits
|
||||
v.offset += bits
|
||||
v.bitsRead += bits
|
||||
}
|
||||
|
||||
// GetByte reads a byte from data
|
||||
func (v *BitMuncher) GetByte() byte {
|
||||
return byte(v.GetBits(8))
|
||||
return byte(v.GetBits(byteLen))
|
||||
}
|
||||
|
||||
// GetInt32 reads an int32 from data
|
||||
func (v *BitMuncher) GetInt32() int32 {
|
||||
return v.MakeSigned(v.GetBits(32), 32)
|
||||
return v.MakeSigned(v.GetBits(fourBytes), fourBytes)
|
||||
}
|
||||
|
||||
// GetUInt32 reads an unsigned uint32 from data
|
||||
func (v *BitMuncher) GetUInt32() uint32 {
|
||||
return v.GetBits(32)
|
||||
return v.GetBits(fourBytes)
|
||||
}
|
||||
|
||||
// GetBits given a number of bits to read, reads that number of
|
||||
// bits and retruns as a uint32
|
||||
func (v *BitMuncher) GetBits(bits int) uint32 {
|
||||
if bits == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
result := uint32(0)
|
||||
for i := 0; i < bits; i++ {
|
||||
result |= v.GetBit() << uint(i)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetSignedBits Given a number of bits, reads that many bits and returns as int
|
||||
func (v *BitMuncher) GetSignedBits(bits int) int {
|
||||
return int(v.MakeSigned(v.GetBits(bits), bits))
|
||||
}
|
||||
|
||||
// MakeSigned converts a uint32 value into an int32
|
||||
func (v *BitMuncher) MakeSigned(value uint32, bits int) int32 {
|
||||
if bits == 0 {
|
||||
return 0
|
||||
@ -73,13 +124,17 @@ func (v *BitMuncher) MakeSigned(value uint32, bits int) int32 {
|
||||
if (value & (1 << uint(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)
|
||||
|
||||
// We need to extend the signed bit out so that the negative value
|
||||
// representation still works with the 2s compliment rule.
|
||||
result := uint32(twosComplimentNegativeOne)
|
||||
|
||||
for i := byte(0); i < byte(bits); i++ {
|
||||
if ((value >> uint(i)) & 1) == 0 {
|
||||
result -= uint32(1 << uint(i))
|
||||
}
|
||||
}
|
||||
|
||||
// Force casting to a signed value
|
||||
return int32(result)
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package d2dcc
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
@ -34,7 +36,7 @@ type DCCDirection struct {
|
||||
}
|
||||
|
||||
// CreateDCCDirection creates an instance of a DCCDirection.
|
||||
func CreateDCCDirection(bm *d2common.BitMuncher, file *DCC) *DCCDirection { //nolint:funlen // Can't reduce
|
||||
func CreateDCCDirection(bm d2interface.BitMuncher, file *DCC) *DCCDirection { //nolint:funlen // Can't reduce
|
||||
var crazyBitTable = []byte{0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32}
|
||||
|
||||
result := &DCCDirection{}
|
||||
@ -130,29 +132,29 @@ func CreateDCCDirection(bm *d2common.BitMuncher, file *DCC) *DCCDirection { //no
|
||||
result.PixelBuffer = nil
|
||||
|
||||
// Verify that everything we expected to read was actually read (sanity check)...
|
||||
if equalCellsBitstream.BitsRead != result.EqualCellsBitstreamSize {
|
||||
if equalCellsBitstream.BitsRead() != result.EqualCellsBitstreamSize {
|
||||
log.Panic("Did not read the correct number of bits!")
|
||||
}
|
||||
|
||||
if pixelMaskBitstream.BitsRead != result.PixelMaskBitstreamSize {
|
||||
if pixelMaskBitstream.BitsRead() != result.PixelMaskBitstreamSize {
|
||||
log.Panic("Did not read the correct number of bits!")
|
||||
}
|
||||
|
||||
if encodingTypeBitsream.BitsRead != result.EncodingTypeBitsreamSize {
|
||||
if encodingTypeBitsream.BitsRead() != result.EncodingTypeBitsreamSize {
|
||||
log.Panic("Did not read the correct number of bits!")
|
||||
}
|
||||
|
||||
if rawPixelCodesBitstream.BitsRead != result.RawPixelCodesBitstreamSize {
|
||||
if rawPixelCodesBitstream.BitsRead() != result.RawPixelCodesBitstreamSize {
|
||||
log.Panic("Did not read the correct number of bits!")
|
||||
}
|
||||
|
||||
bm.SkipBits(pixelCodeandDisplacement.BitsRead)
|
||||
bm.SkipBits(pixelCodeandDisplacement.BitsRead())
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
//nolint:gocognit nolint:gocyclo // Can't reduce
|
||||
func (v *DCCDirection) generateFrames(pcd *d2common.BitMuncher) {
|
||||
func (v *DCCDirection) generateFrames(pcd d2interface.BitMuncher) {
|
||||
pbIdx := 0
|
||||
|
||||
for _, cell := range v.Cells {
|
||||
@ -255,7 +257,7 @@ func (v *DCCDirection) generateFrames(pcd *d2common.BitMuncher) {
|
||||
}
|
||||
|
||||
//nolint:funlen nolint:gocognit // can't reduce
|
||||
func (v *DCCDirection) fillPixelBuffer(pcd, ec, pm, et, rp *d2common.BitMuncher) {
|
||||
func (v *DCCDirection) fillPixelBuffer(pcd, ec, pm, et, rp d2interface.BitMuncher) {
|
||||
var pixelMaskLookup = []int{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}
|
||||
|
||||
lastPixel := uint32(0)
|
||||
|
@ -3,6 +3,8 @@ package d2dcc
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
)
|
||||
|
||||
@ -24,7 +26,7 @@ type DCCDirectionFrame struct {
|
||||
}
|
||||
|
||||
// CreateDCCDirectionFrame Creates a DCCDirectionFrame for a DCC.
|
||||
func CreateDCCDirectionFrame(bits *d2common.BitMuncher, direction *DCCDirection) *DCCDirectionFrame {
|
||||
func CreateDCCDirectionFrame(bits d2interface.BitMuncher, direction *DCCDirection) *DCCDirectionFrame {
|
||||
result := &DCCDirectionFrame{}
|
||||
|
||||
bits.GetBits(direction.Variable0Bits) // Variable0
|
||||
|
18
d2common/d2interface/bitmuncher.go
Normal file
18
d2common/d2interface/bitmuncher.go
Normal file
@ -0,0 +1,18 @@
|
||||
package d2interface
|
||||
|
||||
type BitMuncher interface {
|
||||
Init(data []byte, offset int) BitMuncher
|
||||
Copy() BitMuncher
|
||||
Offset() int
|
||||
SetOffset(int)
|
||||
BitsRead() int
|
||||
SetBitsRead(int)
|
||||
GetBit() uint32
|
||||
SkipBits(bits int)
|
||||
GetByte() byte
|
||||
GetInt32() int32
|
||||
GetUInt32() uint32
|
||||
GetBits(bits int) uint32
|
||||
GetSignedBits(bits int) int
|
||||
MakeSigned(value uint32, bits int) int32
|
||||
}
|
8
d2common/d2interface/bitstream.go
Normal file
8
d2common/d2interface/bitstream.go
Normal file
@ -0,0 +1,8 @@
|
||||
package d2interface
|
||||
|
||||
type BitStream interface {
|
||||
ReadBits(bitCount int) int
|
||||
PeekByte() int
|
||||
EnsureBits(bitCount int) bool
|
||||
WasteBits(bitCount int)
|
||||
}
|
Loading…
Reference in New Issue
Block a user