Move RLE decoding into a separate package
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -9,12 +8,14 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"ur.gs/ordoor/internal/data/rle"
|
||||
)
|
||||
|
||||
type SpriteHeader struct {
|
||||
Unknown0 uint32
|
||||
Width uint16 // FIXME: I'm not certain this is what these are.
|
||||
Height uint16 // FIXME: If they are, they may be the wrong way around
|
||||
Width uint16
|
||||
Height uint16
|
||||
Padding1 uint32 // I don't think this is used. Could be wrong.
|
||||
PixelSize uint32 // Size of PixelData, excluding this sprite header
|
||||
Padding2 uint64 // I don't think this is used either. Could be wrong.
|
||||
@@ -36,7 +37,7 @@ func (s SpriteHeader) Check(expectedSize uint32) error {
|
||||
type Sprite struct {
|
||||
SpriteHeader
|
||||
|
||||
Rows [][]byte
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type dirEntry struct {
|
||||
@@ -132,18 +133,12 @@ func LoadObject(filename string) (*Object, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The pixeldata seems to be formed of Y null-terminated records, with
|
||||
// varying numbers of bytes in each row. I don't know the internal
|
||||
// structure yet, but there's definitely working pixel data in there
|
||||
buf := bufio.NewReader(io.LimitReader(f, int64(sprite.PixelSize)))
|
||||
sprite.Rows = make([][]byte, sprite.Height)
|
||||
buf := io.LimitReader(f, int64(sprite.PixelSize))
|
||||
sprite.Data = make([]byte, sprite.Height*sprite.Width)
|
||||
|
||||
for y := 0; y < int(sprite.Height); y++ {
|
||||
if row, err := buf.ReadBytes(0x00); err != nil {
|
||||
return nil, fmt.Errorf("Reading row %v for sprite %v: %v", y, i, err)
|
||||
} else {
|
||||
sprite.Rows[y] = row
|
||||
}
|
||||
// The pixel data is RLE-compressed. Uncompress it here.
|
||||
if err := rle.Expand(buf, sprite.Data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.Sprites = append(out.Sprites, sprite)
|
||||
|
60
internal/data/rle/rle.go
Normal file
60
internal/data/rle/rle.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// Package rle implements the run-length encoding scheme discovered in Chaos
|
||||
// Gate .obj files. It may be used for other data too - to be determined.
|
||||
package rle
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// Expand converts the compressed input data into uncompressed output data. The
|
||||
// output buffer should be of at least the expected size. We will read until
|
||||
// io.EOF is encountered.
|
||||
func Expand(in io.Reader, out []byte) error {
|
||||
buf := bufio.NewReader(in)
|
||||
idx := 0
|
||||
|
||||
for {
|
||||
b, err := buf.ReadByte()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if b == 0x00 { // NOP
|
||||
continue
|
||||
} else if b < 0x80 { // repeat the next byte this many times
|
||||
repeat := b
|
||||
value, err := buf.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for x := 0; x < int(repeat); x++ {
|
||||
out[idx+x] = value
|
||||
}
|
||||
idx = idx + int(repeat)
|
||||
} else if b == 0x80 { // skip forward in the output by the next byte's value
|
||||
skip, err := buf.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
idx = idx + int(skip)
|
||||
} else { // Take the next b-0x80 bytes literally
|
||||
lr := io.LimitReader(buf, int64(b-0x80))
|
||||
literals, err := ioutil.ReadAll(lr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(out[idx:], literals)
|
||||
idx = idx + len(literals)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user