Resources (WIP)

This commit is contained in:
Milan Nikolic 2017-01-31 10:45:38 +01:00
parent 7132237dcd
commit 3849082a41

210
raylib/rres.go Normal file
View file

@ -0,0 +1,210 @@
package raylib
import (
"bytes"
"compress/flate"
"encoding/binary"
"fmt"
"os"
"unsafe"
)
// rRES file header (8 byte)
type RRESFileHeader struct {
// File identifier: rRES (4 byte)
Id [4]int8
// File version and subversion (2 byte)
Version uint16
// Number of resources in this file (2 byte)
Count uint16
}
// rRES info header, every resource includes this header (16 byte + 16 byte)
type RRESInfoHeader struct {
// Resource unique identifier (4 byte)
Id uint32
// Resource data type (1 byte)
DataType uint8
// Resource data compression type (1 byte)
CompType uint8
// Resource data encryption type (1 byte)
CryptoType uint8
// Resource data parts count, used for splitted data (1 byte)
PartsCount uint8
// Resource data size (compressed or not, only DATA) (4 byte)
DataSize uint32
// Resource data size (uncompressed, only DATA) (4 byte)
UncompSize uint32
// Resouce parameter 1 (4 byte)
Param1 uint32
// Resouce parameter 2 (4 byte)
Param2 uint32
// Resouce parameter 3 (4 byte)
Param3 uint32
// Resouce parameter 4 (4 byte)
Param4 uint32
}
// rRES data types
const (
RRESTypeRaw = iota
RRESTypeImage
RRESTypeWave
RRESTypeVertex
RRESTypeText
RRESTypeFontImage
RRESTypeFontData
RRESTypeDirectory
)
// Compression types
const (
// No data compression
RRESCompNone = iota
// DEFLATE compression
RRESCompDeflate
// LZ4 compression
RRESCompLz4
// LZMA compression
RRESCompLzma
// BROTLI compression
RRESCompBrotli
)
const (
// 8 bit per pixel (no alpha)
RRESImUncompGrayscale = iota + 1
// 16 bpp (2 channels)
RRESImUncompGrayAlpha
// 16 bpp
RRESImUncompR5g6b5
// 24 bpp
RRESImUncompR8g8b8
// 16 bpp (1 bit alpha)
RRESImUncompR5g5b5a1
// 16 bpp (4 bit alpha)
RRESImUncompR4g4b4a4
// 32 bpp
RRESImUncompR8g8b8a8
// 4 bpp (no alpha)
RRESImCompDxt1Rgb
// 4 bpp (1 bit alpha)
RRESImCompDxt1Rgba
// 8 bpp
RRESImCompDxt3Rgba
// 8 bpp
RRESImCompDxt5Rgba
// 4 bpp
RRESImCompEtc1Rgb
// 4 bpp
RRESImCompEtc2Rgb
// 8 bpp
RRESImCompEtc2EacRgba
// 4 bpp
RRESImCompPvrtRgb
// 4 bpp
RRESImCompPvrtRgba
// 8 bpp
RRESImCompAstc4x4Rgba
// 2 bpp
RRESImCompAstc8x8Rgba
)
const (
RRESVertPosition = iota
RRESVertTexcoord1
RRESVertTexcoord2
RRESVertTexcoord3
RRESVertTexcoord4
RRESVertNormal
RRESVertTangent
RRESVertColor
RRESVertIndex
)
const (
RRESVertByte = iota
RRESVertShort
RRESVertInt
RRESVertHfloat
RRESVertFloat
)
// Load resource from file (only one)
// NOTE: Returns uncompressed data with parameters, only first resource found
func LoadResource(fileName string) []byte {
return LoadResourceById(fileName, 0)
}
// Load resource from file by id
// NOTE: Returns uncompressed data with parameters, search resource by id
func LoadResourceById(fileName string, rresId int) (data []byte) {
file, err := os.Open(fileName)
if err != nil {
TraceLog(LogWarning, "[%s] rRES raylib resource file could not be opened", fileName)
return
}
defer file.Close()
fileHeader := RRESFileHeader{}
infoHeader := RRESInfoHeader{}
// Read rres file header
err = binary.Read(file, binary.LittleEndian, &fileHeader)
if err != nil {
TraceLog(LogWarning, err.Error())
return
}
//fmt.Printf("%+v\n", fileHeader)
// Verify "rRES" identifier
id := fmt.Sprintf("%c", fileHeader.Id)
if id != "[r R E S]" {
TraceLog(LogWarning, "[%s] This is not a valid raylib resource file", fileName)
return
}
file.Seek(int64(unsafe.Sizeof(fileHeader)), os.SEEK_CUR)
for i := 0; i < int(fileHeader.Count); i++ {
// Read resource info and parameters
err = binary.Read(file, binary.LittleEndian, &infoHeader)
if err != nil {
TraceLog(LogWarning, err.Error())
return
}
//fmt.Printf("%+v\n", infoHeader)
file.Seek(int64(unsafe.Sizeof(infoHeader)), os.SEEK_CUR)
if int(infoHeader.Id) == rresId {
// Read resource data block
data = make([]byte, infoHeader.DataSize)
file.Read(data)
if infoHeader.CompType == RRESCompDeflate {
// Uncompress data
b := bytes.NewReader(data)
r := flate.NewReader(b)
data = make([]byte, infoHeader.UncompSize)
r.Read(data)
}
if len(data) > 0 {
TraceLog(LogInfo, "[%s][ID %d] Resource data loaded successfully", fileName, infoHeader.Id)
}
} else {
// Skip required data to read next resource infoHeader
file.Seek(int64(infoHeader.DataSize), os.SEEK_CUR)
}
}
if len(data) == 0 {
TraceLog(LogInfo, "[%s][ID %d] Requested resource could not be found", fileName, rresId)
}
return
}