2018-12-14 04:03:47 +00:00
|
|
|
package dc6
|
2018-12-17 02:07:24 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
2018-12-17 19:29:01 +00:00
|
|
|
|
2018-12-17 02:07:24 +00:00
|
|
|
"io"
|
2018-12-17 19:29:01 +00:00
|
|
|
|
|
|
|
"github.com/FooSoft/lazarus/streaming"
|
2018-12-17 02:07:24 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
FlagIsSerialized = 1 << iota
|
|
|
|
FlagIsLoadedInHw
|
|
|
|
FlagIs24Bits
|
|
|
|
)
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
type fileHeader struct {
|
2018-12-17 02:07:24 +00:00
|
|
|
Version uint32
|
|
|
|
Flags uint32
|
|
|
|
Format uint32
|
|
|
|
SkipColor uint32
|
|
|
|
DirCount uint32
|
|
|
|
FramesPerDir uint32
|
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
type frameHeader struct {
|
2018-12-17 02:07:24 +00:00
|
|
|
Flip uint32
|
|
|
|
Width uint32
|
|
|
|
Height uint32
|
|
|
|
OffsetX uint32
|
|
|
|
OffsetY uint32
|
|
|
|
AllocSize uint32
|
|
|
|
NextBlock uint32
|
2018-12-17 03:30:53 +00:00
|
|
|
Length uint32
|
2018-12-17 02:07:24 +00:00
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
type Direction struct {
|
|
|
|
Frames []Frame
|
|
|
|
}
|
|
|
|
|
2018-12-17 02:07:24 +00:00
|
|
|
type Frame struct {
|
|
|
|
Width int
|
|
|
|
Height int
|
|
|
|
OffsetX int
|
|
|
|
OffsetY int
|
|
|
|
Data []byte
|
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
type Sprite struct {
|
|
|
|
Directions []Direction
|
2018-12-17 02:07:24 +00:00
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
func New(reader io.ReadSeeker) (*Sprite, error) {
|
|
|
|
sprite := new(Sprite)
|
2018-12-17 02:07:24 +00:00
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
var fileHead fileHeader
|
|
|
|
if err := binary.Read(reader, binary.LittleEndian, &fileHead); err != nil {
|
2018-12-17 02:07:24 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
frameCount := int(fileHead.DirCount * fileHead.FramesPerDir)
|
|
|
|
|
2018-12-17 02:07:24 +00:00
|
|
|
var frameOffsets []uint32
|
2018-12-17 19:45:43 +00:00
|
|
|
for i := 0; i < frameCount; i++ {
|
2018-12-17 02:07:24 +00:00
|
|
|
var frameOffset uint32
|
|
|
|
if err := binary.Read(reader, binary.LittleEndian, &frameOffset); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
frameOffsets = append(frameOffsets, frameOffset)
|
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
sprite.Directions = make([]Direction, fileHead.FramesPerDir)
|
|
|
|
|
|
|
|
for i := 0; i < frameCount; i++ {
|
|
|
|
var frameHead frameHeader
|
|
|
|
if _, err := reader.Seek(int64(frameOffsets[i]), io.SeekStart); err != nil {
|
2018-12-17 02:07:24 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
if err := binary.Read(reader, binary.LittleEndian, &frameHead); err != nil {
|
2018-12-17 02:07:24 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
data := make([]byte, frameHead.Width*frameHead.Height)
|
2018-12-17 19:29:01 +00:00
|
|
|
writer := streaming.NewWriter(data)
|
2018-12-17 19:45:43 +00:00
|
|
|
if err := extractFrame(reader, writer, frameHead); err != nil {
|
2018-12-17 03:30:53 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-12-17 02:07:24 +00:00
|
|
|
frame := Frame{
|
2018-12-17 19:45:43 +00:00
|
|
|
int(frameHead.Width),
|
|
|
|
int(frameHead.Height),
|
|
|
|
int(frameHead.OffsetX),
|
|
|
|
int(frameHead.OffsetY),
|
2018-12-17 19:29:01 +00:00
|
|
|
data,
|
2018-12-17 02:07:24 +00:00
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
direction := &sprite.Directions[i/int(fileHead.FramesPerDir)]
|
|
|
|
direction.Frames = append(direction.Frames, frame)
|
2018-12-17 02:07:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sprite, nil
|
|
|
|
}
|
|
|
|
|
2018-12-17 19:45:43 +00:00
|
|
|
func extractFrame(reader io.ReadSeeker, writer io.WriteSeeker, header frameHeader) error {
|
2018-12-17 03:30:53 +00:00
|
|
|
var (
|
|
|
|
x uint32
|
|
|
|
y = header.Height - 1
|
|
|
|
)
|
|
|
|
|
|
|
|
var offset uint32
|
|
|
|
for offset < header.Length {
|
|
|
|
var chunkSize byte
|
|
|
|
if err := binary.Read(reader, binary.LittleEndian, &chunkSize); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if chunkSize == 0x80 {
|
|
|
|
x = 0
|
|
|
|
y--
|
|
|
|
} else if (chunkSize & 0x80) != 0 {
|
|
|
|
x += uint32(chunkSize & 0x7f)
|
|
|
|
} else {
|
|
|
|
if _, err := writer.Seek(int64(header.Width*y+x), io.SeekStart); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if _, err := io.CopyN(writer, reader, int64(chunkSize)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
offset += uint32(chunkSize)
|
|
|
|
x += uint32(chunkSize)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-17 02:07:24 +00:00
|
|
|
return nil
|
|
|
|
}
|