diff --git a/formats/dcc/dcc.go b/formats/dcc/dcc.go index c37bef7..b184cb6 100644 --- a/formats/dcc/dcc.go +++ b/formats/dcc/dcc.go @@ -2,10 +2,7 @@ package dcc import ( "encoding/binary" - "errors" "io" - - "github.com/FooSoft/lazarus/streaming" ) type Sprite struct { @@ -27,39 +24,8 @@ type fileHeader struct { FinalDc6Size uint32 } -type directionHeader struct { - CodedSize uint32 - HasRawPixelEncoding bool - CompressEqualCells bool - Variable0Bits uint8 - WidthBits uint8 - HeightBits uint8 - OffsetXBits uint8 - OffsetYBits uint8 - OptionalBytesBits uint8 - CodedBytesBits uint8 -} - -type direction struct { - header directionHeader - frames []frame - bounds bounds -} - -type frameHeader struct { - Variable0 uint32 - Width uint32 - Height uint32 - OffsetX int32 - OffsetY int32 - OptionalBytes uint32 - CodedBytes uint32 - FrameBottomUp bool -} - -type frame struct { - header frameHeader - bounds bounds +type pixelBufferEntry struct { + values [4]byte } func NewFromReader(reader io.ReadSeeker) (*Sprite, error) { @@ -97,105 +63,3 @@ func NewFromReader(reader io.ReadSeeker) (*Sprite, error) { return nil, nil } - -func readDirectionHeader(bitReader *streaming.BitReader) directionHeader { - var dirHead directionHeader - - dirHead.CodedSize = uint32(bitReader.ReadUint(32)) - dirHead.HasRawPixelEncoding = bitReader.ReadBool() - dirHead.CompressEqualCells = bitReader.ReadBool() - dirHead.Variable0Bits = uint8(bitReader.ReadUint(4)) - dirHead.WidthBits = uint8(bitReader.ReadUint(4)) - dirHead.HeightBits = uint8(bitReader.ReadUint(4)) - dirHead.OffsetXBits = uint8(bitReader.ReadInt(4)) - dirHead.OffsetYBits = uint8(bitReader.ReadInt(4)) - dirHead.OptionalBytesBits = uint8(bitReader.ReadUint(4)) - dirHead.CodedBytesBits = uint8(bitReader.ReadUint(4)) - - return dirHead -} - -func readFrameHeader(bitReader *streaming.BitReader, dirHead directionHeader) frameHeader { - var frameHead frameHeader - - frameHead.Variable0 = uint32(bitReader.ReadUintPacked(int(dirHead.Variable0Bits))) - frameHead.Width = uint32(bitReader.ReadUintPacked(int(dirHead.WidthBits))) - frameHead.Height = uint32(bitReader.ReadUintPacked(int(dirHead.HeightBits))) - frameHead.OffsetX = int32(bitReader.ReadIntPacked(int(dirHead.OffsetXBits))) - frameHead.OffsetY = int32(bitReader.ReadIntPacked(int(dirHead.OffsetYBits))) - frameHead.OptionalBytes = uint32(bitReader.ReadUintPacked(int(dirHead.OptionalBytesBits))) - frameHead.CodedBytes = uint32(bitReader.ReadUintPacked(int(dirHead.CodedBytesBits))) - frameHead.FrameBottomUp = bitReader.ReadBool() - - return frameHead -} - -func readFrameHeaders(bitReader *streaming.BitReader, fileHead fileHeader, dirHead directionHeader) ([]frameHeader, error) { - var frameHeads []frameHeader - for i := 0; i < int(fileHead.FramesPerDir); i++ { - frameHead := readFrameHeader(bitReader, dirHead) - if err := bitReader.Error(); err != nil { - return nil, err - } - - if frameHead.OptionalBytes != 0 { - return nil, errors.New("optional frame data not supported") - } - - if frameHead.FrameBottomUp { - return nil, errors.New("bottom-up frames are not supported") - } - - frameHeads = append(frameHeads, frameHead) - } - - return frameHeads, nil -} - -func readDirection(reader io.ReadSeeker, fileHead fileHeader) (*direction, error) { - bitReader := streaming.NewBitReader(reader) - - dirHead := readDirectionHeader(bitReader) - if err := bitReader.Error(); err != nil { - return nil, err - } - - frameHeads, err := readFrameHeaders(bitReader, fileHead, dirHead) - if err != nil { - return nil, err - } - - var dirData direction - for i, frameHead := range frameHeads { - frameData := frame{ - header: frameHead, - bounds: bounds{ - x1: int(frameHead.OffsetX), - y1: int(frameHead.OffsetY) - int(frameHead.Height) + 1, - x2: int(frameHead.OffsetX) + int(frameHead.Width), - y2: int(frameHead.OffsetY) + 1, - }, - } - - dirData.frames = append(dirData.frames, frameData) - - if i == 0 { - dirData.bounds = frameData.bounds - } else { - if dirData.bounds.x1 > frameData.bounds.x1 { - dirData.bounds.x1 = frameData.bounds.x1 - } - if dirData.bounds.y1 > frameData.bounds.y1 { - dirData.bounds.y1 = frameData.bounds.y1 - } - if dirData.bounds.x2 < frameData.bounds.x2 { - dirData.bounds.x2 = frameData.bounds.x2 - } - if dirData.bounds.y2 < frameData.bounds.y2 { - dirData.bounds.y2 = frameData.bounds.y2 - } - } - } - - return &dirData, nil -} diff --git a/formats/dcc/direction.go b/formats/dcc/direction.go new file mode 100644 index 0000000..6b6188a --- /dev/null +++ b/formats/dcc/direction.go @@ -0,0 +1,111 @@ +package dcc + +import ( + "io" + + "github.com/FooSoft/lazarus/streaming" +) + +type directionHeader struct { + CodedSize uint32 + HasRawPixelEncoding bool + CompressEqualCells bool + Variable0Bits uint8 + WidthBits uint8 + HeightBits uint8 + OffsetXBits uint8 + OffsetYBits uint8 + OptionalBytesBits uint8 + CodedBytesBits uint8 +} + +type direction struct { + header directionHeader + frames []frame + bounds bounds +} + +func readDirectionHeader(bitReader *streaming.BitReader) directionHeader { + var dirHead directionHeader + + dirHead.CodedSize = uint32(bitReader.ReadUint(32)) + dirHead.HasRawPixelEncoding = bitReader.ReadBool() + dirHead.CompressEqualCells = bitReader.ReadBool() + dirHead.Variable0Bits = uint8(bitReader.ReadUint(4)) + dirHead.WidthBits = uint8(bitReader.ReadUint(4)) + dirHead.HeightBits = uint8(bitReader.ReadUint(4)) + dirHead.OffsetXBits = uint8(bitReader.ReadInt(4)) + dirHead.OffsetYBits = uint8(bitReader.ReadInt(4)) + dirHead.OptionalBytesBits = uint8(bitReader.ReadUint(4)) + dirHead.CodedBytesBits = uint8(bitReader.ReadUint(4)) + + return dirHead +} + +func readDirection(reader io.ReadSeeker, fileHead fileHeader) (*direction, error) { + bitReader := streaming.NewBitReader(reader) + + dirHead := readDirectionHeader(bitReader) + if err := bitReader.Error(); err != nil { + return nil, err + } + + frameHeads, err := readFrameHeaders(bitReader, fileHead, dirHead) + if err != nil { + return nil, err + } + + var dirData direction + for i, frameHead := range frameHeads { + frameData := frame{ + header: frameHead, + bounds: bounds{ + x1: int(frameHead.OffsetX), + y1: int(frameHead.OffsetY) - int(frameHead.Height) + 1, + x2: int(frameHead.OffsetX) + int(frameHead.Width), + y2: int(frameHead.OffsetY) + 1, + }, + } + + dirData.frames = append(dirData.frames, frameData) + + if i == 0 { + dirData.bounds = frameData.bounds + } else { + if dirData.bounds.x1 > frameData.bounds.x1 { + dirData.bounds.x1 = frameData.bounds.x1 + } + if dirData.bounds.y1 > frameData.bounds.y1 { + dirData.bounds.y1 = frameData.bounds.y1 + } + if dirData.bounds.x2 < frameData.bounds.x2 { + dirData.bounds.x2 = frameData.bounds.x2 + } + if dirData.bounds.y2 < frameData.bounds.y2 { + dirData.bounds.y2 = frameData.bounds.y2 + } + } + } + + var entries []pixelBufferEntry + + entries, err = decodeDirectionStage1(bitReader, &dirData, entries) + if err != nil { + return nil, err + } + + entries, err = decodeDirectionStage2(bitReader, &dirData, entries) + if err != nil { + return nil, err + } + + return &dirData, nil +} + +func decodeDirectionStage1(bitReader *streaming.BitReader, dirData *direction, entries []pixelBufferEntry) ([]pixelBufferEntry, error) { + return nil, nil +} + +func decodeDirectionStage2(bitReader *streaming.BitReader, dirData *direction, entries []pixelBufferEntry) ([]pixelBufferEntry, error) { + return nil, nil +} diff --git a/formats/dcc/frame.go b/formats/dcc/frame.go new file mode 100644 index 0000000..8464354 --- /dev/null +++ b/formats/dcc/frame.go @@ -0,0 +1,64 @@ +package dcc + +import ( + "errors" + + "github.com/FooSoft/lazarus/streaming" +) + +type frameHeader struct { + Variable0 uint32 + Width uint32 + Height uint32 + OffsetX int32 + OffsetY int32 + OptionalBytes uint32 + CodedBytes uint32 + FrameBottomUp bool +} + +type frame struct { + header frameHeader + bounds bounds +} + +func readFrameHeader(bitReader *streaming.BitReader, dirHead directionHeader) frameHeader { + var frameHead frameHeader + + frameHead.Variable0 = uint32(bitReader.ReadUintPacked(int(dirHead.Variable0Bits))) + frameHead.Width = uint32(bitReader.ReadUintPacked(int(dirHead.WidthBits))) + frameHead.Height = uint32(bitReader.ReadUintPacked(int(dirHead.HeightBits))) + frameHead.OffsetX = int32(bitReader.ReadIntPacked(int(dirHead.OffsetXBits))) + frameHead.OffsetY = int32(bitReader.ReadIntPacked(int(dirHead.OffsetYBits))) + frameHead.OptionalBytes = uint32(bitReader.ReadUintPacked(int(dirHead.OptionalBytesBits))) + frameHead.CodedBytes = uint32(bitReader.ReadUintPacked(int(dirHead.CodedBytesBits))) + frameHead.FrameBottomUp = bitReader.ReadBool() + + return frameHead +} + +func readFrameHeaders(bitReader *streaming.BitReader, fileHead fileHeader, dirHead directionHeader) ([]frameHeader, error) { + var frameHeads []frameHeader + for i := 0; i < int(fileHead.FramesPerDir); i++ { + frameHead := readFrameHeader(bitReader, dirHead) + if err := bitReader.Error(); err != nil { + return nil, err + } + + if frameHead.OptionalBytes != 0 { + return nil, errors.New("optional frame data not supported") + } + + if frameHead.FrameBottomUp { + return nil, errors.New("bottom-up frames are not supported") + } + + if frameHead.Width == 0 || frameHead.Height == 0 { + return nil, errors.New("invalid frame dimensions") + } + + frameHeads = append(frameHeads, frameHead) + } + + return frameHeads, nil +}