rres rewrite (update sources, create go-types, add some functions)
This commit is contained in:
parent
d84e4cc82f
commit
fb93c7c94b
18 changed files with 12042 additions and 1284 deletions
|
@ -1,27 +0,0 @@
|
||||||
## rrem
|
|
||||||
|
|
||||||
rREM - raylib Resource EMbedder.
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
Usage of ./rrem:
|
|
||||||
-base string
|
|
||||||
Resources file basename (default "data")
|
|
||||||
-bin
|
|
||||||
Generate Go bindata (.go file)
|
|
||||||
-comp int
|
|
||||||
Compression type, 0=NONE, 1=DEFLATE, 2=LZ4, 5=LZMA2 (XZ), 6=BZIP2, 7=Snappy (default 1)
|
|
||||||
-enc int
|
|
||||||
Encryption type, 0=NONE, 1=XOR, 2=AES, 3=3DES, 4=Blowfish, 5=XTEA
|
|
||||||
-header
|
|
||||||
Generate C header (.h file)
|
|
||||||
-key string
|
|
||||||
Encryption key
|
|
||||||
-source
|
|
||||||
Generate C source (.c file)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
[Example](https://github.com/gen2brain/raylib-go/tree/master/examples/others/resources).
|
|
|
@ -1,19 +0,0 @@
|
||||||
module rrem
|
|
||||||
|
|
||||||
go 1.16
|
|
||||||
|
|
||||||
replace github.com/gen2brain/raylib-go/raylib => ../../../raylib
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/blezek/tga v0.0.0-20150626111426-80720cbc1017
|
|
||||||
github.com/ftrvxmtrx/tga v0.0.0-20150524081124-bd8e8d5be13a // indirect
|
|
||||||
github.com/gen2brain/raylib-go/raylib v0.0.0-20230307115054-60f06875ad1a // indirect
|
|
||||||
github.com/gen2brain/raylib-go/rres v0.0.0-20230307115054-60f06875ad1a
|
|
||||||
github.com/jbuchbinder/gopnm v0.0.0-20150223212718-5176c556b9ce
|
|
||||||
github.com/jfreymuth/oggvorbis v1.0.3
|
|
||||||
github.com/jteeuwen/go-bindata v3.0.7+incompatible
|
|
||||||
github.com/klauspost/compress v1.16.0 // indirect
|
|
||||||
github.com/moutend/go-wav v0.0.0-20170820031854-56127fbbb7ba
|
|
||||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
|
||||||
)
|
|
|
@ -1,85 +0,0 @@
|
||||||
github.com/blezek/tga v0.0.0-20150626111426-80720cbc1017 h1:TWk6m6k3qegbUZsdsHk/ix22ANqPgLau40bPwiNQN40=
|
|
||||||
github.com/blezek/tga v0.0.0-20150626111426-80720cbc1017/go.mod h1:WnX8JiQN+UtyUPq/1EIUaB2WVX3wdAmOBH5K52NyOO0=
|
|
||||||
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
|
|
||||||
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
|
|
||||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
|
||||||
github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk=
|
|
||||||
github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU=
|
|
||||||
github.com/ftrvxmtrx/tga v0.0.0-20150524081124-bd8e8d5be13a h1:eSqaRmdlZ9JsJ7JuWfDr3ym3monToXRczohBOL+heVQ=
|
|
||||||
github.com/ftrvxmtrx/tga v0.0.0-20150524081124-bd8e8d5be13a/go.mod h1:US5WvgEHtG+BvWNNs6gk937h0QL2g2x+r7RH8m3g80Y=
|
|
||||||
github.com/gen2brain/raylib-go/rres v0.0.0-20230307115054-60f06875ad1a h1:6IduVkjrSqp+F4L2v2ZBrqqyr/N3u/aDRy9XSZc1HTo=
|
|
||||||
github.com/gen2brain/raylib-go/rres v0.0.0-20230307115054-60f06875ad1a/go.mod h1:toaFdqokQRKoToQuVkSZCH0L8My5oOorXENs2NX8XJc=
|
|
||||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/jbuchbinder/gopnm v0.0.0-20150223212718-5176c556b9ce h1:SHuC5z27u3lD7x5aybCGdCMN9U01n1+bsaTGfJUPvlc=
|
|
||||||
github.com/jbuchbinder/gopnm v0.0.0-20150223212718-5176c556b9ce/go.mod h1:k4IRLYBcpoQAIqDzFcBFY3eSoVnCvN5nfq3Wqm0ZLp8=
|
|
||||||
github.com/jfreymuth/oggvorbis v1.0.3 h1:MLNGGyhOMiVcvea9Dp5+gbs2SAwqwQbtrWnonYa0M0Y=
|
|
||||||
github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
|
||||||
github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE=
|
|
||||||
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
|
|
||||||
github.com/jteeuwen/go-bindata v3.0.7+incompatible h1:91Uy4d9SYVr1kyTJ15wJsog+esAZZl7JmEfTkwmhJts=
|
|
||||||
github.com/jteeuwen/go-bindata v3.0.7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs=
|
|
||||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
|
||||||
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
|
||||||
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
|
||||||
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
|
||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/moutend/go-wav v0.0.0-20170820031854-56127fbbb7ba h1:OjLj0dIkgDrGzgLHh2dv2BGtpa8RwCqykn2ThFcOMLc=
|
|
||||||
github.com/moutend/go-wav v0.0.0-20170820031854-56127fbbb7ba/go.mod h1:y/Ls9PBADL6vJfbt4gZbNtUS2grnEGnFg4RMsCa5g/4=
|
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
|
||||||
github.com/rootlch/encrypt v0.0.0-20120717064446-58e7f47a860b h1:06aiugVMPXHO5St9bxSpm2N2uowHODq2sPozLO+gclo=
|
|
||||||
github.com/rootlch/encrypt v0.0.0-20120717064446-58e7f47a860b/go.mod h1:X9D5dzJkrZcrZB5tJCL06gaWACx7V8IvFIiONW2foko=
|
|
||||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
|
||||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
|
||||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
|
||||||
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
||||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
|
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
|
@ -1,434 +0,0 @@
|
||||||
// rREM - raylib Resource EMbedder
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"image/draw"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
_ "image/gif"
|
|
||||||
_ "image/jpeg"
|
|
||||||
_ "image/png"
|
|
||||||
|
|
||||||
"github.com/blezek/tga"
|
|
||||||
_ "github.com/jbuchbinder/gopnm"
|
|
||||||
_ "golang.org/x/image/bmp"
|
|
||||||
|
|
||||||
"github.com/jfreymuth/oggvorbis"
|
|
||||||
"github.com/jteeuwen/go-bindata"
|
|
||||||
"github.com/moutend/go-wav"
|
|
||||||
|
|
||||||
"github.com/gen2brain/raylib-go/rres"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
tga.RegisterFormat()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
base := flag.String("base", "data", "Resources file basename")
|
|
||||||
comp := flag.Int("comp", rres.CompDeflate, "Compression type, 0=NONE, 1=DEFLATE, 2=LZ4, 5=LZMA2 (XZ), 6=BZIP2, 7=Snappy")
|
|
||||||
enc := flag.Int("enc", rres.CryptoNone, "Encryption type, 0=NONE, 1=XOR, 2=AES, 3=3DES, 4=Blowfish, 5=XTEA")
|
|
||||||
key := flag.String("key", "", "Encryption key")
|
|
||||||
header := flag.Bool("header", false, "Generate C header (.h file)")
|
|
||||||
source := flag.Bool("source", false, "Generate C source (.c file)")
|
|
||||||
bin := flag.Bool("bin", false, "Generate Go bindata (.go file)")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if len(flag.Args()) == 0 {
|
|
||||||
flag.Usage()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !validComp(*comp) {
|
|
||||||
fmt.Printf("compression type %d not implemented\n", *comp)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !validEnc(*enc) {
|
|
||||||
fmt.Printf("encryption type %d not implemented\n", *enc)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *enc != 0 {
|
|
||||||
if *key == "" {
|
|
||||||
fmt.Printf("encryption requires key (-k)\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if len(*key) != 16 && len(*key) != 24 {
|
|
||||||
fmt.Printf("wrong key length, it should be 16 or 24\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rresFile, err := os.Create(fmt.Sprintf("%s.rres", *base))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var headerFile *os.File
|
|
||||||
if *header {
|
|
||||||
headerFile, err = os.Create(fmt.Sprintf("%s.h", *base))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer headerFile.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
var sourceFile *os.File
|
|
||||||
if *source {
|
|
||||||
sourceFile, err = os.Create(fmt.Sprintf("%s.c", *base))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer sourceFile.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileHeader rres.FileHeader
|
|
||||||
|
|
||||||
// "rRES" identifier
|
|
||||||
copy(fileHeader.ID[:], "rRES")
|
|
||||||
fileHeader.Count = uint16(len(flag.Args()))
|
|
||||||
fileHeader.Version = 1
|
|
||||||
|
|
||||||
// Write file header
|
|
||||||
err = binary.Write(rresFile, binary.LittleEndian, &fileHeader)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
rresFile.Seek(int64(unsafe.Sizeof(fileHeader)), os.SEEK_CUR)
|
|
||||||
|
|
||||||
if *header {
|
|
||||||
// Write C header file
|
|
||||||
_, err = headerFile.Write([]byte(fmt.Sprintf("#define NUM_RESOURCES %d\n\n", flag.NArg())))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for id, filename := range flag.Args() {
|
|
||||||
var data []byte
|
|
||||||
var infoHeader rres.InfoHeader
|
|
||||||
|
|
||||||
file, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s: %v\n", filename, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err = ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s: %v\n", filename, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file.Close()
|
|
||||||
|
|
||||||
infoHeader.ID = uint32(id)
|
|
||||||
infoHeader.CompType = uint8(*comp)
|
|
||||||
infoHeader.CryptoType = uint8(*enc)
|
|
||||||
infoHeader.DataType = uint8(fileType(filename))
|
|
||||||
infoHeader.PartsCount = uint8(1)
|
|
||||||
|
|
||||||
// Params
|
|
||||||
data, infoHeader.Param1, infoHeader.Param2, infoHeader.Param3, infoHeader.Param4, err = params(data, int(infoHeader.DataType))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s: %v\n", filename, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encryption
|
|
||||||
data, err = rres.Encrypt([]byte(*key), data, int(infoHeader.CryptoType))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
infoHeader.UncompSize = uint32(len(data))
|
|
||||||
|
|
||||||
// Compression
|
|
||||||
data, err = rres.Compress(data, int(infoHeader.CompType))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
infoHeader.DataSize = uint32(len(data))
|
|
||||||
|
|
||||||
// Write resource info and parameters
|
|
||||||
err = binary.Write(rresFile, binary.LittleEndian, &infoHeader)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rresFile.Seek(int64(unsafe.Sizeof(infoHeader)), os.SEEK_CUR)
|
|
||||||
|
|
||||||
// Write resource data
|
|
||||||
_, err = rresFile.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%s %d // Embedded as %s\n", filepath.Base(filename), id, typeName(int(infoHeader.DataType)))
|
|
||||||
|
|
||||||
if *header {
|
|
||||||
headerFile.Write([]byte(fmt.Sprintf("#define RES_%s 0x%08x\t\t// Embedded as %s\n", filepath.Base(filename), id, typeName(int(infoHeader.DataType)))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = rresFile.Sync()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = rresFile.Close()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate C source
|
|
||||||
if *source {
|
|
||||||
fname := fmt.Sprintf("%s.rres", *base)
|
|
||||||
file, err := os.Open(fname)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s: %v\n", fname, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
d, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s: %v\n", fname, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file.Close()
|
|
||||||
|
|
||||||
err = genSource(sourceFile, d)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate Go bindata
|
|
||||||
if *bin {
|
|
||||||
err = genBin(*base)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fileType returns resource file type
|
|
||||||
func fileType(f string) int {
|
|
||||||
switch strings.ToLower(filepath.Ext(f)) {
|
|
||||||
case ".jpg", ".jpeg", ".png", ".bmp", ".tga", ".gif":
|
|
||||||
return rres.TypeImage
|
|
||||||
case ".txt", ".csv", ".info", ".md":
|
|
||||||
return rres.TypeText
|
|
||||||
case ".wav":
|
|
||||||
return rres.TypeWave
|
|
||||||
case ".ogg":
|
|
||||||
return rres.TypeVorbis
|
|
||||||
case ".obj":
|
|
||||||
return rres.TypeVertex
|
|
||||||
default:
|
|
||||||
return rres.TypeRaw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// typeName returns data type name
|
|
||||||
func typeName(dataType int) string {
|
|
||||||
switch dataType {
|
|
||||||
case rres.TypeImage:
|
|
||||||
return "IMAGE"
|
|
||||||
case rres.TypeWave:
|
|
||||||
return "WAVE"
|
|
||||||
case rres.TypeVorbis:
|
|
||||||
return "VORBIS"
|
|
||||||
case rres.TypeText:
|
|
||||||
return "TEXT"
|
|
||||||
default:
|
|
||||||
return "RAW"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// validEnc checks if encryption type is valid
|
|
||||||
func validEnc(encType int) bool {
|
|
||||||
switch encType {
|
|
||||||
case rres.CryptoNone, rres.CryptoXOR:
|
|
||||||
return true
|
|
||||||
case rres.CryptoAES, rres.Crypto3DES:
|
|
||||||
return true
|
|
||||||
case rres.CryptoBlowfish, rres.CryptoXTEA:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// validComp checks if compression type is valid
|
|
||||||
func validComp(compType int) bool {
|
|
||||||
switch compType {
|
|
||||||
case rres.CompNone, rres.CompDeflate:
|
|
||||||
return true
|
|
||||||
case rres.CompLZ4, rres.CompLZMA2:
|
|
||||||
return true
|
|
||||||
case rres.CompBZIP2, rres.CompSnappy:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// params returns data params
|
|
||||||
func params(data []byte, dataType int) (d []byte, p1, p2, p3, p4 uint32, err error) {
|
|
||||||
switch dataType {
|
|
||||||
case rres.TypeImage:
|
|
||||||
var img image.Image
|
|
||||||
|
|
||||||
img, _, err = image.Decode(bytes.NewReader(data))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rect := img.Bounds()
|
|
||||||
width, height := rect.Dx(), rect.Dy()
|
|
||||||
|
|
||||||
p1 = uint32(width)
|
|
||||||
p2 = uint32(height)
|
|
||||||
|
|
||||||
switch img.ColorModel() {
|
|
||||||
case color.GrayModel:
|
|
||||||
p3 = rres.ImUncompGrayscale
|
|
||||||
|
|
||||||
i := image.NewGray(rect)
|
|
||||||
draw.Draw(i, rect, img, rect.Min, draw.Src)
|
|
||||||
d = i.Pix
|
|
||||||
return
|
|
||||||
case color.Gray16Model:
|
|
||||||
p3 = rres.ImUncompGrayAlpha
|
|
||||||
|
|
||||||
i := image.NewGray16(rect)
|
|
||||||
draw.Draw(i, rect, img, rect.Min, draw.Src)
|
|
||||||
d = i.Pix
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
p3 = rres.ImUncompR8g8b8a8
|
|
||||||
|
|
||||||
i := image.NewNRGBA(rect)
|
|
||||||
draw.Draw(i, rect, img, rect.Min, draw.Src)
|
|
||||||
d = i.Pix
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case rres.TypeWave:
|
|
||||||
a := &wav.File{}
|
|
||||||
err = wav.Unmarshal(data, a)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
d, err = ioutil.ReadAll(a)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p1 = uint32(a.Samples())
|
|
||||||
p2 = uint32(a.SamplesPerSec())
|
|
||||||
p3 = uint32(a.BitsPerSample())
|
|
||||||
p4 = uint32(a.Channels())
|
|
||||||
return
|
|
||||||
case rres.TypeVorbis:
|
|
||||||
r, e := oggvorbis.NewReader(bytes.NewReader(data))
|
|
||||||
if e != nil {
|
|
||||||
err = e
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
o, _, e := oggvorbis.ReadAll(bytes.NewReader(data))
|
|
||||||
if e != nil {
|
|
||||||
err = e
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert []float32 to []byte
|
|
||||||
header := *(*reflect.SliceHeader)(unsafe.Pointer(&o))
|
|
||||||
header.Len *= 4
|
|
||||||
header.Cap *= 4
|
|
||||||
d = *(*[]byte)(unsafe.Pointer(&header))
|
|
||||||
|
|
||||||
p1 = uint32(r.SampleRate())
|
|
||||||
p2 = uint32(r.Bitrate().Nominal)
|
|
||||||
p3 = uint32(r.Channels())
|
|
||||||
return
|
|
||||||
case rres.TypeVertex:
|
|
||||||
// TODO https://github.com/sheenobu/go-obj
|
|
||||||
case rres.TypeText, rres.TypeRaw:
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// genSource generates C source file
|
|
||||||
func genSource(w io.Writer, data []byte) error {
|
|
||||||
length := len(data)
|
|
||||||
|
|
||||||
_, err := w.Write([]byte("// This file has been automatically generated by rREM - raylib Resource Embedder\n\n"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write([]byte(fmt.Sprintf("const unsigned char data[%d] = {\n ", length)))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
blCounter := 0 // break line counter
|
|
||||||
|
|
||||||
for i := 0; i < len(data)-1; i++ {
|
|
||||||
blCounter++
|
|
||||||
|
|
||||||
_, err = w.Write([]byte(fmt.Sprintf("0x%.2x, ", data[i])))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if blCounter >= 24 {
|
|
||||||
_, err = w.Write([]byte("\n "))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
blCounter = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write([]byte(fmt.Sprintf("0x%.2x };\n", data[length-1])))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// genBin generates go-bindata file
|
|
||||||
func genBin(base string) error {
|
|
||||||
cfg := bindata.NewConfig()
|
|
||||||
cfg.NoCompress = true
|
|
||||||
cfg.Output = fmt.Sprintf("%s.go", base)
|
|
||||||
cfg.Input = make([]bindata.InputConfig, 1)
|
|
||||||
cfg.Input[0] = bindata.InputConfig{Path: fmt.Sprintf("%s.rres", base), Recursive: false}
|
|
||||||
|
|
||||||
return bindata.Translate(cfg)
|
|
||||||
}
|
|
572
rres/external/aes.c
vendored
Normal file
572
rres/external/aes.c
vendored
Normal file
|
@ -0,0 +1,572 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode.
|
||||||
|
Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.
|
||||||
|
|
||||||
|
The implementation is verified against the test vectors in:
|
||||||
|
National Institute of Standards and Technology Special Publication 800-38A 2001 ED
|
||||||
|
|
||||||
|
ECB-AES128
|
||||||
|
----------
|
||||||
|
|
||||||
|
plain-text:
|
||||||
|
6bc1bee22e409f96e93d7e117393172a
|
||||||
|
ae2d8a571e03ac9c9eb76fac45af8e51
|
||||||
|
30c81c46a35ce411e5fbc1191a0a52ef
|
||||||
|
f69f2445df4f9b17ad2b417be66c3710
|
||||||
|
|
||||||
|
key:
|
||||||
|
2b7e151628aed2a6abf7158809cf4f3c
|
||||||
|
|
||||||
|
resulting cipher
|
||||||
|
3ad77bb40d7a3660a89ecaf32466ef97
|
||||||
|
f5d3d58503b9699de785895a96fdbaaf
|
||||||
|
43b1cd7f598ece23881b00e3ed030688
|
||||||
|
7b0c785e27e8ad3f8223207104725dd4
|
||||||
|
|
||||||
|
|
||||||
|
NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
|
||||||
|
You should pad the end of the string with zeros if this is not the case.
|
||||||
|
For AES192/256 the key size is proportionally larger.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Includes: */
|
||||||
|
/*****************************************************************************/
|
||||||
|
#include <string.h> // CBC mode, for memset
|
||||||
|
#include "aes.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Defines: */
|
||||||
|
/*****************************************************************************/
|
||||||
|
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
|
||||||
|
#define Nb 4
|
||||||
|
|
||||||
|
#if defined(AES256) && (AES256 == 1)
|
||||||
|
#define Nk 8
|
||||||
|
#define Nr 14
|
||||||
|
#elif defined(AES192) && (AES192 == 1)
|
||||||
|
#define Nk 6
|
||||||
|
#define Nr 12
|
||||||
|
#else
|
||||||
|
#define Nk 4 // The number of 32 bit words in a key.
|
||||||
|
#define Nr 10 // The number of rounds in AES Cipher.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// jcallan@github points out that declaring Multiply as a function
|
||||||
|
// reduces code size considerably with the Keil ARM compiler.
|
||||||
|
// See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3
|
||||||
|
#ifndef MULTIPLY_AS_A_FUNCTION
|
||||||
|
#define MULTIPLY_AS_A_FUNCTION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Private variables: */
|
||||||
|
/*****************************************************************************/
|
||||||
|
// state - array holding the intermediate results during decryption.
|
||||||
|
typedef uint8_t state_t[4][4];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
|
||||||
|
// The numbers below can be computed dynamically trading ROM for RAM -
|
||||||
|
// This can be useful in (embedded) bootloader applications, where ROM is often limited.
|
||||||
|
static const uint8_t sbox[256] = {
|
||||||
|
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
|
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||||
|
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||||
|
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||||
|
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||||
|
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||||
|
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||||
|
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||||
|
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||||
|
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||||
|
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||||
|
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||||
|
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||||
|
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||||
|
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||||
|
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||||
|
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
|
||||||
|
|
||||||
|
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
|
||||||
|
static const uint8_t rsbox[256] = {
|
||||||
|
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||||
|
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||||
|
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||||
|
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||||
|
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||||
|
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||||
|
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||||
|
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||||
|
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||||
|
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||||
|
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||||
|
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||||
|
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||||
|
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||||
|
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||||
|
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The round constant word array, Rcon[i], contains the values given by
|
||||||
|
// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
|
||||||
|
static const uint8_t Rcon[11] = {
|
||||||
|
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12),
|
||||||
|
* that you can remove most of the elements in the Rcon array, because they are unused.
|
||||||
|
*
|
||||||
|
* From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
|
||||||
|
*
|
||||||
|
* "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed),
|
||||||
|
* up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Private functions: */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*
|
||||||
|
static uint8_t getSBoxValue(uint8_t num)
|
||||||
|
{
|
||||||
|
return sbox[num];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#define getSBoxValue(num) (sbox[(num)])
|
||||||
|
|
||||||
|
// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
|
||||||
|
static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key)
|
||||||
|
{
|
||||||
|
unsigned i, j, k;
|
||||||
|
uint8_t tempa[4]; // Used for the column/row operations
|
||||||
|
|
||||||
|
// The first round key is the key itself.
|
||||||
|
for (i = 0; i < Nk; ++i)
|
||||||
|
{
|
||||||
|
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
|
||||||
|
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
|
||||||
|
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
|
||||||
|
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other round keys are found from the previous round keys.
|
||||||
|
for (i = Nk; i < Nb * (Nr + 1); ++i)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
k = (i - 1) * 4;
|
||||||
|
tempa[0]=RoundKey[k + 0];
|
||||||
|
tempa[1]=RoundKey[k + 1];
|
||||||
|
tempa[2]=RoundKey[k + 2];
|
||||||
|
tempa[3]=RoundKey[k + 3];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i % Nk == 0)
|
||||||
|
{
|
||||||
|
// This function shifts the 4 bytes in a word to the left once.
|
||||||
|
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
|
||||||
|
|
||||||
|
// Function RotWord()
|
||||||
|
{
|
||||||
|
const uint8_t u8tmp = tempa[0];
|
||||||
|
tempa[0] = tempa[1];
|
||||||
|
tempa[1] = tempa[2];
|
||||||
|
tempa[2] = tempa[3];
|
||||||
|
tempa[3] = u8tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubWord() is a function that takes a four-byte input word and
|
||||||
|
// applies the S-box to each of the four bytes to produce an output word.
|
||||||
|
|
||||||
|
// Function Subword()
|
||||||
|
{
|
||||||
|
tempa[0] = getSBoxValue(tempa[0]);
|
||||||
|
tempa[1] = getSBoxValue(tempa[1]);
|
||||||
|
tempa[2] = getSBoxValue(tempa[2]);
|
||||||
|
tempa[3] = getSBoxValue(tempa[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tempa[0] = tempa[0] ^ Rcon[i/Nk];
|
||||||
|
}
|
||||||
|
#if defined(AES256) && (AES256 == 1)
|
||||||
|
if (i % Nk == 4)
|
||||||
|
{
|
||||||
|
// Function Subword()
|
||||||
|
{
|
||||||
|
tempa[0] = getSBoxValue(tempa[0]);
|
||||||
|
tempa[1] = getSBoxValue(tempa[1]);
|
||||||
|
tempa[2] = getSBoxValue(tempa[2]);
|
||||||
|
tempa[3] = getSBoxValue(tempa[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
j = i * 4; k=(i - Nk) * 4;
|
||||||
|
RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
|
||||||
|
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
|
||||||
|
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
|
||||||
|
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key)
|
||||||
|
{
|
||||||
|
KeyExpansion(ctx->RoundKey, key);
|
||||||
|
}
|
||||||
|
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
|
||||||
|
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv)
|
||||||
|
{
|
||||||
|
KeyExpansion(ctx->RoundKey, key);
|
||||||
|
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
|
||||||
|
}
|
||||||
|
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv)
|
||||||
|
{
|
||||||
|
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This function adds the round key to state.
|
||||||
|
// The round key is added to the state by an XOR function.
|
||||||
|
static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey)
|
||||||
|
{
|
||||||
|
uint8_t i,j;
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 4; ++j)
|
||||||
|
{
|
||||||
|
(*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The SubBytes Function Substitutes the values in the
|
||||||
|
// state matrix with values in an S-box.
|
||||||
|
static void SubBytes(state_t* state)
|
||||||
|
{
|
||||||
|
uint8_t i, j;
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 4; ++j)
|
||||||
|
{
|
||||||
|
(*state)[j][i] = getSBoxValue((*state)[j][i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ShiftRows() function shifts the rows in the state to the left.
|
||||||
|
// Each row is shifted with different offset.
|
||||||
|
// Offset = Row number. So the first row is not shifted.
|
||||||
|
static void ShiftRows(state_t* state)
|
||||||
|
{
|
||||||
|
uint8_t temp;
|
||||||
|
|
||||||
|
// Rotate first row 1 columns to left
|
||||||
|
temp = (*state)[0][1];
|
||||||
|
(*state)[0][1] = (*state)[1][1];
|
||||||
|
(*state)[1][1] = (*state)[2][1];
|
||||||
|
(*state)[2][1] = (*state)[3][1];
|
||||||
|
(*state)[3][1] = temp;
|
||||||
|
|
||||||
|
// Rotate second row 2 columns to left
|
||||||
|
temp = (*state)[0][2];
|
||||||
|
(*state)[0][2] = (*state)[2][2];
|
||||||
|
(*state)[2][2] = temp;
|
||||||
|
|
||||||
|
temp = (*state)[1][2];
|
||||||
|
(*state)[1][2] = (*state)[3][2];
|
||||||
|
(*state)[3][2] = temp;
|
||||||
|
|
||||||
|
// Rotate third row 3 columns to left
|
||||||
|
temp = (*state)[0][3];
|
||||||
|
(*state)[0][3] = (*state)[3][3];
|
||||||
|
(*state)[3][3] = (*state)[2][3];
|
||||||
|
(*state)[2][3] = (*state)[1][3];
|
||||||
|
(*state)[1][3] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t xtime(uint8_t x)
|
||||||
|
{
|
||||||
|
return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
|
||||||
|
}
|
||||||
|
|
||||||
|
// MixColumns function mixes the columns of the state matrix
|
||||||
|
static void MixColumns(state_t* state)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t Tmp, Tm, t;
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
t = (*state)[i][0];
|
||||||
|
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
|
||||||
|
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
|
||||||
|
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
|
||||||
|
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
|
||||||
|
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply is used to multiply numbers in the field GF(2^8)
|
||||||
|
// Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary
|
||||||
|
// The compiler seems to be able to vectorize the operation better this way.
|
||||||
|
// See https://github.com/kokke/tiny-AES-c/pull/34
|
||||||
|
#if MULTIPLY_AS_A_FUNCTION
|
||||||
|
static uint8_t Multiply(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
return (((y & 1) * x) ^
|
||||||
|
((y>>1 & 1) * xtime(x)) ^
|
||||||
|
((y>>2 & 1) * xtime(xtime(x))) ^
|
||||||
|
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
|
||||||
|
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define Multiply(x, y) \
|
||||||
|
( ((y & 1) * x) ^ \
|
||||||
|
((y>>1 & 1) * xtime(x)) ^ \
|
||||||
|
((y>>2 & 1) * xtime(xtime(x))) ^ \
|
||||||
|
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
|
||||||
|
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
|
||||||
|
/*
|
||||||
|
static uint8_t getSBoxInvert(uint8_t num)
|
||||||
|
{
|
||||||
|
return rsbox[num];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#define getSBoxInvert(num) (rsbox[(num)])
|
||||||
|
|
||||||
|
// MixColumns function mixes the columns of the state matrix.
|
||||||
|
// The method used to multiply may be difficult to understand for the inexperienced.
|
||||||
|
// Please use the references to gain more information.
|
||||||
|
static void InvMixColumns(state_t* state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t a, b, c, d;
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
a = (*state)[i][0];
|
||||||
|
b = (*state)[i][1];
|
||||||
|
c = (*state)[i][2];
|
||||||
|
d = (*state)[i][3];
|
||||||
|
|
||||||
|
(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
|
||||||
|
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
|
||||||
|
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
|
||||||
|
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The SubBytes Function Substitutes the values in the
|
||||||
|
// state matrix with values in an S-box.
|
||||||
|
static void InvSubBytes(state_t* state)
|
||||||
|
{
|
||||||
|
uint8_t i, j;
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 4; ++j)
|
||||||
|
{
|
||||||
|
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InvShiftRows(state_t* state)
|
||||||
|
{
|
||||||
|
uint8_t temp;
|
||||||
|
|
||||||
|
// Rotate first row 1 columns to right
|
||||||
|
temp = (*state)[3][1];
|
||||||
|
(*state)[3][1] = (*state)[2][1];
|
||||||
|
(*state)[2][1] = (*state)[1][1];
|
||||||
|
(*state)[1][1] = (*state)[0][1];
|
||||||
|
(*state)[0][1] = temp;
|
||||||
|
|
||||||
|
// Rotate second row 2 columns to right
|
||||||
|
temp = (*state)[0][2];
|
||||||
|
(*state)[0][2] = (*state)[2][2];
|
||||||
|
(*state)[2][2] = temp;
|
||||||
|
|
||||||
|
temp = (*state)[1][2];
|
||||||
|
(*state)[1][2] = (*state)[3][2];
|
||||||
|
(*state)[3][2] = temp;
|
||||||
|
|
||||||
|
// Rotate third row 3 columns to right
|
||||||
|
temp = (*state)[0][3];
|
||||||
|
(*state)[0][3] = (*state)[1][3];
|
||||||
|
(*state)[1][3] = (*state)[2][3];
|
||||||
|
(*state)[2][3] = (*state)[3][3];
|
||||||
|
(*state)[3][3] = temp;
|
||||||
|
}
|
||||||
|
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
|
||||||
|
|
||||||
|
// Cipher is the main function that encrypts the PlainText.
|
||||||
|
static void Cipher(state_t* state, const uint8_t* RoundKey)
|
||||||
|
{
|
||||||
|
uint8_t round = 0;
|
||||||
|
|
||||||
|
// Add the First round key to the state before starting the rounds.
|
||||||
|
AddRoundKey(0, state, RoundKey);
|
||||||
|
|
||||||
|
// There will be Nr rounds.
|
||||||
|
// The first Nr-1 rounds are identical.
|
||||||
|
// These Nr rounds are executed in the loop below.
|
||||||
|
// Last one without MixColumns()
|
||||||
|
for (round = 1; ; ++round)
|
||||||
|
{
|
||||||
|
SubBytes(state);
|
||||||
|
ShiftRows(state);
|
||||||
|
if (round == Nr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MixColumns(state);
|
||||||
|
AddRoundKey(round, state, RoundKey);
|
||||||
|
}
|
||||||
|
// Add round key to last round
|
||||||
|
AddRoundKey(Nr, state, RoundKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
|
||||||
|
static void InvCipher(state_t* state, const uint8_t* RoundKey)
|
||||||
|
{
|
||||||
|
uint8_t round = 0;
|
||||||
|
|
||||||
|
// Add the First round key to the state before starting the rounds.
|
||||||
|
AddRoundKey(Nr, state, RoundKey);
|
||||||
|
|
||||||
|
// There will be Nr rounds.
|
||||||
|
// The first Nr-1 rounds are identical.
|
||||||
|
// These Nr rounds are executed in the loop below.
|
||||||
|
// Last one without InvMixColumn()
|
||||||
|
for (round = (Nr - 1); ; --round)
|
||||||
|
{
|
||||||
|
InvShiftRows(state);
|
||||||
|
InvSubBytes(state);
|
||||||
|
AddRoundKey(round, state, RoundKey);
|
||||||
|
if (round == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
InvMixColumns(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Public functions: */
|
||||||
|
/*****************************************************************************/
|
||||||
|
#if defined(ECB) && (ECB == 1)
|
||||||
|
|
||||||
|
|
||||||
|
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf)
|
||||||
|
{
|
||||||
|
// The next function call encrypts the PlainText with the Key using AES algorithm.
|
||||||
|
Cipher((state_t*)buf, ctx->RoundKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf)
|
||||||
|
{
|
||||||
|
// The next function call decrypts the PlainText with the Key using AES algorithm.
|
||||||
|
InvCipher((state_t*)buf, ctx->RoundKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #if defined(ECB) && (ECB == 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CBC) && (CBC == 1)
|
||||||
|
|
||||||
|
|
||||||
|
static void XorWithIv(uint8_t* buf, const uint8_t* Iv)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size
|
||||||
|
{
|
||||||
|
buf[i] ^= Iv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, size_t length)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
uint8_t *Iv = ctx->Iv;
|
||||||
|
for (i = 0; i < length; i += AES_BLOCKLEN)
|
||||||
|
{
|
||||||
|
XorWithIv(buf, Iv);
|
||||||
|
Cipher((state_t*)buf, ctx->RoundKey);
|
||||||
|
Iv = buf;
|
||||||
|
buf += AES_BLOCKLEN;
|
||||||
|
}
|
||||||
|
/* store Iv in ctx for next call */
|
||||||
|
memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
uint8_t storeNextIv[AES_BLOCKLEN];
|
||||||
|
for (i = 0; i < length; i += AES_BLOCKLEN)
|
||||||
|
{
|
||||||
|
memcpy(storeNextIv, buf, AES_BLOCKLEN);
|
||||||
|
InvCipher((state_t*)buf, ctx->RoundKey);
|
||||||
|
XorWithIv(buf, ctx->Iv);
|
||||||
|
memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);
|
||||||
|
buf += AES_BLOCKLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #if defined(CBC) && (CBC == 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CTR) && (CTR == 1)
|
||||||
|
|
||||||
|
/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */
|
||||||
|
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length)
|
||||||
|
{
|
||||||
|
uint8_t buffer[AES_BLOCKLEN];
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
int bi;
|
||||||
|
for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
|
||||||
|
{
|
||||||
|
if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */
|
||||||
|
{
|
||||||
|
|
||||||
|
memcpy(buffer, ctx->Iv, AES_BLOCKLEN);
|
||||||
|
Cipher((state_t*)buffer,ctx->RoundKey);
|
||||||
|
|
||||||
|
/* Increment Iv and handle overflow */
|
||||||
|
for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
|
||||||
|
{
|
||||||
|
/* inc will overflow */
|
||||||
|
if (ctx->Iv[bi] == 255)
|
||||||
|
{
|
||||||
|
ctx->Iv[bi] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ctx->Iv[bi] += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[i] = (buf[i] ^ buffer[bi]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #if defined(CTR) && (CTR == 1)
|
||||||
|
|
91
rres/external/aes.h
vendored
Normal file
91
rres/external/aes.h
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#ifndef _AES_H_
|
||||||
|
#define _AES_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// #define the macros below to 1/0 to enable/disable the mode of operation.
|
||||||
|
//
|
||||||
|
// CBC enables AES encryption in CBC-mode of operation.
|
||||||
|
// CTR enables encryption in counter-mode.
|
||||||
|
// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously.
|
||||||
|
|
||||||
|
// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
|
||||||
|
#ifndef CBC
|
||||||
|
#define CBC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ECB
|
||||||
|
#define ECB 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CTR
|
||||||
|
#define CTR 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//#define AES128 1
|
||||||
|
//#define AES192 1
|
||||||
|
#define AES256 1
|
||||||
|
|
||||||
|
#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only
|
||||||
|
|
||||||
|
#if defined(AES256) && (AES256 == 1)
|
||||||
|
#define AES_KEYLEN 32
|
||||||
|
#define AES_keyExpSize 240
|
||||||
|
#elif defined(AES192) && (AES192 == 1)
|
||||||
|
#define AES_KEYLEN 24
|
||||||
|
#define AES_keyExpSize 208
|
||||||
|
#else
|
||||||
|
#define AES_KEYLEN 16 // Key length in bytes
|
||||||
|
#define AES_keyExpSize 176
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct AES_ctx
|
||||||
|
{
|
||||||
|
uint8_t RoundKey[AES_keyExpSize];
|
||||||
|
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
|
||||||
|
uint8_t Iv[AES_BLOCKLEN];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
|
||||||
|
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
|
||||||
|
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
|
||||||
|
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ECB) && (ECB == 1)
|
||||||
|
// buffer size is exactly AES_BLOCKLEN bytes;
|
||||||
|
// you need only AES_init_ctx as IV is not used in ECB
|
||||||
|
// NB: ECB is considered insecure for most uses
|
||||||
|
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf);
|
||||||
|
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf);
|
||||||
|
|
||||||
|
#endif // #if defined(ECB) && (ECB == !)
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CBC) && (CBC == 1)
|
||||||
|
// buffer size MUST be mutile of AES_BLOCKLEN;
|
||||||
|
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
|
||||||
|
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
|
||||||
|
// no IV should ever be reused with the same key
|
||||||
|
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
|
||||||
|
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
|
||||||
|
|
||||||
|
#endif // #if defined(CBC) && (CBC == 1)
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CTR) && (CTR == 1)
|
||||||
|
|
||||||
|
// Same function for encrypting as for decrypting.
|
||||||
|
// IV is incremented for every block, and used after encryption as XOR-compliment for output
|
||||||
|
// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
|
||||||
|
// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
|
||||||
|
// no IV should ever be reused with the same key
|
||||||
|
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
|
||||||
|
|
||||||
|
#endif // #if defined(CTR) && (CTR == 1)
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _AES_H_
|
2526
rres/external/lz4.c
vendored
Normal file
2526
rres/external/lz4.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
785
rres/external/lz4.h
vendored
Normal file
785
rres/external/lz4.h
vendored
Normal file
|
@ -0,0 +1,785 @@
|
||||||
|
/*
|
||||||
|
* LZ4 - Fast LZ compression algorithm
|
||||||
|
* Header File
|
||||||
|
* Copyright (C) 2011-2020, Yann Collet.
|
||||||
|
|
||||||
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
You can contact the author at :
|
||||||
|
- LZ4 homepage : http://www.lz4.org
|
||||||
|
- LZ4 source repository : https://github.com/lz4/lz4
|
||||||
|
*/
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LZ4_H_2983827168210
|
||||||
|
#define LZ4_H_2983827168210
|
||||||
|
|
||||||
|
/* --- Dependency --- */
|
||||||
|
#include <stddef.h> /* size_t */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,
|
||||||
|
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
|
||||||
|
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
|
||||||
|
|
||||||
|
The LZ4 compression library provides in-memory compression and decompression functions.
|
||||||
|
It gives full buffer control to user.
|
||||||
|
Compression can be done in:
|
||||||
|
- a single step (described as Simple Functions)
|
||||||
|
- a single step, reusing a context (described in Advanced Functions)
|
||||||
|
- unbounded multiple steps (described as Streaming compression)
|
||||||
|
|
||||||
|
lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
|
||||||
|
Decompressing such a compressed block requires additional metadata.
|
||||||
|
Exact metadata depends on exact decompression function.
|
||||||
|
For the typical case of LZ4_decompress_safe(),
|
||||||
|
metadata includes block's compressed size, and maximum bound of decompressed size.
|
||||||
|
Each application is free to encode and pass such metadata in whichever way it wants.
|
||||||
|
|
||||||
|
lz4.h only handle blocks, it can not generate Frames.
|
||||||
|
|
||||||
|
Blocks are different from Frames (doc/lz4_Frame_format.md).
|
||||||
|
Frames bundle both blocks and metadata in a specified manner.
|
||||||
|
Embedding metadata is required for compressed data to be self-contained and portable.
|
||||||
|
Frame format is delivered through a companion API, declared in lz4frame.h.
|
||||||
|
The `lz4` CLI can only manage frames.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*^***************************************************************
|
||||||
|
* Export parameters
|
||||||
|
*****************************************************************/
|
||||||
|
/*
|
||||||
|
* LZ4_DLL_EXPORT :
|
||||||
|
* Enable exporting of functions when building a Windows DLL
|
||||||
|
* LZ4LIB_VISIBILITY :
|
||||||
|
* Control library symbols visibility.
|
||||||
|
*/
|
||||||
|
#ifndef LZ4LIB_VISIBILITY
|
||||||
|
# if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||||
|
# else
|
||||||
|
# define LZ4LIB_VISIBILITY
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
|
||||||
|
# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
|
||||||
|
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
|
||||||
|
# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||||
|
#else
|
||||||
|
# define LZ4LIB_API LZ4LIB_VISIBILITY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*------ Version ------*/
|
||||||
|
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||||
|
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
|
||||||
|
#define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */
|
||||||
|
|
||||||
|
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||||
|
|
||||||
|
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
|
||||||
|
#define LZ4_QUOTE(str) #str
|
||||||
|
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
|
||||||
|
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)
|
||||||
|
|
||||||
|
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */
|
||||||
|
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version */
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Tuning parameter
|
||||||
|
**************************************/
|
||||||
|
#define LZ4_MEMORY_USAGE_MIN 10
|
||||||
|
#define LZ4_MEMORY_USAGE_DEFAULT 14
|
||||||
|
#define LZ4_MEMORY_USAGE_MAX 20
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* LZ4_MEMORY_USAGE :
|
||||||
|
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; )
|
||||||
|
* Increasing memory usage improves compression ratio, at the cost of speed.
|
||||||
|
* Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.
|
||||||
|
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
||||||
|
*/
|
||||||
|
#ifndef LZ4_MEMORY_USAGE
|
||||||
|
# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)
|
||||||
|
# error "LZ4_MEMORY_USAGE is too small !"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)
|
||||||
|
# error "LZ4_MEMORY_USAGE is too large !"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Simple Functions
|
||||||
|
**************************************/
|
||||||
|
/*! LZ4_compress_default() :
|
||||||
|
* Compresses 'srcSize' bytes from buffer 'src'
|
||||||
|
* into already allocated 'dst' buffer of size 'dstCapacity'.
|
||||||
|
* Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
|
||||||
|
* It also runs faster, so it's a recommended setting.
|
||||||
|
* If the function cannot compress 'src' into a more limited 'dst' budget,
|
||||||
|
* compression stops *immediately*, and the function result is zero.
|
||||||
|
* In which case, 'dst' content is undefined (invalid).
|
||||||
|
* srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
|
||||||
|
* dstCapacity : size of buffer 'dst' (which must be already allocated)
|
||||||
|
* @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
|
||||||
|
* or 0 if compression fails
|
||||||
|
* Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
|
||||||
|
|
||||||
|
/*! LZ4_decompress_safe() :
|
||||||
|
* compressedSize : is the exact complete size of the compressed block.
|
||||||
|
* dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size.
|
||||||
|
* @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
|
||||||
|
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
|
||||||
|
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||||
|
* Note 1 : This function is protected against malicious data packets :
|
||||||
|
* it will never writes outside 'dst' buffer, nor read outside 'source' buffer,
|
||||||
|
* even if the compressed block is maliciously modified to order the decoder to do these actions.
|
||||||
|
* In such case, the decoder stops immediately, and considers the compressed block malformed.
|
||||||
|
* Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.
|
||||||
|
* The implementation is free to send / store / derive this information in whichever way is most beneficial.
|
||||||
|
* If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Advanced Functions
|
||||||
|
**************************************/
|
||||||
|
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||||
|
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||||
|
|
||||||
|
/*! LZ4_compressBound() :
|
||||||
|
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
|
||||||
|
This function is primarily useful for memory allocation purposes (destination buffer size).
|
||||||
|
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||||
|
Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)
|
||||||
|
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
|
||||||
|
return : maximum output size in a "worst case" scenario
|
||||||
|
or 0, if input size is incorrect (too large or negative)
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compressBound(int inputSize);
|
||||||
|
|
||||||
|
/*! LZ4_compress_fast() :
|
||||||
|
Same as LZ4_compress_default(), but allows selection of "acceleration" factor.
|
||||||
|
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||||
|
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||||
|
An acceleration value of "1" is the same as regular LZ4_compress_default()
|
||||||
|
Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).
|
||||||
|
Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_compress_fast_extState() :
|
||||||
|
* Same as LZ4_compress_fast(), using an externally allocated memory space for its state.
|
||||||
|
* Use LZ4_sizeofState() to know how much memory must be allocated,
|
||||||
|
* and allocate it on 8-bytes boundaries (using `malloc()` typically).
|
||||||
|
* Then, provide this buffer as `void* state` to compression function.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_sizeofState(void);
|
||||||
|
LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_compress_destSize() :
|
||||||
|
* Reverse the logic : compresses as much data as possible from 'src' buffer
|
||||||
|
* into already allocated buffer 'dst', of size >= 'targetDestSize'.
|
||||||
|
* This function either compresses the entire 'src' content into 'dst' if it's large enough,
|
||||||
|
* or fill 'dst' buffer completely with as much data as possible from 'src'.
|
||||||
|
* note: acceleration parameter is fixed to "default".
|
||||||
|
*
|
||||||
|
* *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
|
||||||
|
* New value is necessarily <= input value.
|
||||||
|
* @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
|
||||||
|
* or 0 if compression fails.
|
||||||
|
*
|
||||||
|
* Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+):
|
||||||
|
* the produced compressed content could, in specific circumstances,
|
||||||
|
* require to be decompressed into a destination buffer larger
|
||||||
|
* by at least 1 byte than the content to decompress.
|
||||||
|
* If an application uses `LZ4_compress_destSize()`,
|
||||||
|
* it's highly recommended to update liblz4 to v1.9.2 or better.
|
||||||
|
* If this can't be done or ensured,
|
||||||
|
* the receiving decompression function should provide
|
||||||
|
* a dstCapacity which is > decompressedSize, by at least 1 byte.
|
||||||
|
* See https://github.com/lz4/lz4/issues/859 for details
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_decompress_safe_partial() :
|
||||||
|
* Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
|
||||||
|
* into destination buffer 'dst' of size 'dstCapacity'.
|
||||||
|
* Up to 'targetOutputSize' bytes will be decoded.
|
||||||
|
* The function stops decoding on reaching this objective.
|
||||||
|
* This can be useful to boost performance
|
||||||
|
* whenever only the beginning of a block is required.
|
||||||
|
*
|
||||||
|
* @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)
|
||||||
|
* If source stream is detected malformed, function returns a negative result.
|
||||||
|
*
|
||||||
|
* Note 1 : @return can be < targetOutputSize, if compressed block contains less data.
|
||||||
|
*
|
||||||
|
* Note 2 : targetOutputSize must be <= dstCapacity
|
||||||
|
*
|
||||||
|
* Note 3 : this function effectively stops decoding on reaching targetOutputSize,
|
||||||
|
* so dstCapacity is kind of redundant.
|
||||||
|
* This is because in older versions of this function,
|
||||||
|
* decoding operation would still write complete sequences.
|
||||||
|
* Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,
|
||||||
|
* it could write more bytes, though only up to dstCapacity.
|
||||||
|
* Some "margin" used to be required for this operation to work properly.
|
||||||
|
* Thankfully, this is no longer necessary.
|
||||||
|
* The function nonetheless keeps the same signature, in an effort to preserve API compatibility.
|
||||||
|
*
|
||||||
|
* Note 4 : If srcSize is the exact size of the block,
|
||||||
|
* then targetOutputSize can be any value,
|
||||||
|
* including larger than the block's decompressed size.
|
||||||
|
* The function will, at most, generate block's decompressed size.
|
||||||
|
*
|
||||||
|
* Note 5 : If srcSize is _larger_ than block's compressed size,
|
||||||
|
* then targetOutputSize **MUST** be <= block's decompressed size.
|
||||||
|
* Otherwise, *silent corruption will occur*.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
|
||||||
|
|
||||||
|
|
||||||
|
/*-*********************************************
|
||||||
|
* Streaming Compression Functions
|
||||||
|
***********************************************/
|
||||||
|
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
|
||||||
|
|
||||||
|
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
|
||||||
|
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
||||||
|
|
||||||
|
/*! LZ4_resetStream_fast() : v1.9.0+
|
||||||
|
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
|
||||||
|
* (e.g., LZ4_compress_fast_continue()).
|
||||||
|
*
|
||||||
|
* An LZ4_stream_t must be initialized once before usage.
|
||||||
|
* This is automatically done when created by LZ4_createStream().
|
||||||
|
* However, should the LZ4_stream_t be simply declared on stack (for example),
|
||||||
|
* it's necessary to initialize it first, using LZ4_initStream().
|
||||||
|
*
|
||||||
|
* After init, start any new stream with LZ4_resetStream_fast().
|
||||||
|
* A same LZ4_stream_t can be re-used multiple times consecutively
|
||||||
|
* and compress multiple streams,
|
||||||
|
* provided that it starts each new stream with LZ4_resetStream_fast().
|
||||||
|
*
|
||||||
|
* LZ4_resetStream_fast() is much faster than LZ4_initStream(),
|
||||||
|
* but is not compatible with memory regions containing garbage data.
|
||||||
|
*
|
||||||
|
* Note: it's only useful to call LZ4_resetStream_fast()
|
||||||
|
* in the context of streaming compression.
|
||||||
|
* The *extState* functions perform their own resets.
|
||||||
|
* Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
|
||||||
|
|
||||||
|
/*! LZ4_loadDict() :
|
||||||
|
* Use this function to reference a static dictionary into LZ4_stream_t.
|
||||||
|
* The dictionary must remain available during compression.
|
||||||
|
* LZ4_loadDict() triggers a reset, so any previous data will be forgotten.
|
||||||
|
* The same dictionary will have to be loaded on decompression side for successful decoding.
|
||||||
|
* Dictionary are useful for better compression of small data (KB range).
|
||||||
|
* While LZ4 accept any input as dictionary,
|
||||||
|
* results are generally better when using Zstandard's Dictionary Builder.
|
||||||
|
* Loading a size of 0 is allowed, and is the same as reset.
|
||||||
|
* @return : loaded dictionary size, in bytes (necessarily <= 64 KB)
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||||
|
|
||||||
|
/*! LZ4_compress_fast_continue() :
|
||||||
|
* Compress 'src' content using data from previously compressed blocks, for better compression ratio.
|
||||||
|
* 'dst' buffer must be already allocated.
|
||||||
|
* If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
|
||||||
|
*
|
||||||
|
* @return : size of compressed block
|
||||||
|
* or 0 if there is an error (typically, cannot fit into 'dst').
|
||||||
|
*
|
||||||
|
* Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block.
|
||||||
|
* Each block has precise boundaries.
|
||||||
|
* Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata.
|
||||||
|
* It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together.
|
||||||
|
*
|
||||||
|
* Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory !
|
||||||
|
*
|
||||||
|
* Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB.
|
||||||
|
* Make sure that buffers are separated, by at least one byte.
|
||||||
|
* This construction ensures that each block only depends on previous block.
|
||||||
|
*
|
||||||
|
* Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
|
||||||
|
*
|
||||||
|
* Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
|
/*! LZ4_saveDict() :
|
||||||
|
* If last 64KB data cannot be guaranteed to remain available at its current memory location,
|
||||||
|
* save it into a safer place (char* safeBuffer).
|
||||||
|
* This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
|
||||||
|
* but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.
|
||||||
|
* @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
|
||||||
|
|
||||||
|
|
||||||
|
/*-**********************************************
|
||||||
|
* Streaming Decompression Functions
|
||||||
|
* Bufferless synchronous API
|
||||||
|
************************************************/
|
||||||
|
typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
|
||||||
|
|
||||||
|
/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
|
||||||
|
* creation / destruction of streaming decompression tracking context.
|
||||||
|
* A tracking context can be re-used multiple times.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
|
||||||
|
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
||||||
|
|
||||||
|
/*! LZ4_setStreamDecode() :
|
||||||
|
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
|
||||||
|
* Use this function to start decompression of a new stream of blocks.
|
||||||
|
* A dictionary can optionally be set. Use NULL or size 0 for a reset order.
|
||||||
|
* Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
|
||||||
|
* @return : 1 if OK, 0 if error
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
|
||||||
|
|
||||||
|
/*! LZ4_decoderRingBufferSize() : v1.8.2+
|
||||||
|
* Note : in a ring buffer scenario (optional),
|
||||||
|
* blocks are presumed decompressed next to each other
|
||||||
|
* up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),
|
||||||
|
* at which stage it resumes from beginning of ring buffer.
|
||||||
|
* When setting such a ring buffer for streaming decompression,
|
||||||
|
* provides the minimum size of this ring buffer
|
||||||
|
* to be compatible with any source respecting maxBlockSize condition.
|
||||||
|
* @return : minimum ring buffer size,
|
||||||
|
* or 0 if there is an error (invalid maxBlockSize).
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
|
||||||
|
#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */
|
||||||
|
|
||||||
|
/*! LZ4_decompress_*_continue() :
|
||||||
|
* These decoding functions allow decompression of consecutive blocks in "streaming" mode.
|
||||||
|
* A block is an unsplittable entity, it must be presented entirely to a decompression function.
|
||||||
|
* Decompression functions only accepts one block at a time.
|
||||||
|
* The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded.
|
||||||
|
* If less than 64KB of data has been decoded, all the data must be present.
|
||||||
|
*
|
||||||
|
* Special : if decompression side sets a ring buffer, it must respect one of the following conditions :
|
||||||
|
* - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).
|
||||||
|
* maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.
|
||||||
|
* In which case, encoding and decoding buffers do not need to be synchronized.
|
||||||
|
* Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.
|
||||||
|
* - Synchronized mode :
|
||||||
|
* Decompression buffer size is _exactly_ the same as compression buffer size,
|
||||||
|
* and follows exactly same update rule (block boundaries at same positions),
|
||||||
|
* and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),
|
||||||
|
* _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||||
|
* - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.
|
||||||
|
* In which case, encoding and decoding buffers do not need to be synchronized,
|
||||||
|
* and encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||||
|
*
|
||||||
|
* Whenever these conditions are not possible,
|
||||||
|
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
|
||||||
|
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_decompress_*_usingDict() :
|
||||||
|
* These decoding functions work the same as
|
||||||
|
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
|
||||||
|
* They are stand-alone, and don't need an LZ4_streamDecode_t structure.
|
||||||
|
* Dictionary is presumed stable : it must remain accessible and unmodified during decompression.
|
||||||
|
* Performance tip : Decompression speed can be substantially increased
|
||||||
|
* when dst == dictStart + dictSize.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
|
||||||
|
|
||||||
|
#endif /* LZ4_H_2983827168210 */
|
||||||
|
|
||||||
|
|
||||||
|
/*^*************************************
|
||||||
|
* !!!!!! STATIC LINKING ONLY !!!!!!
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
/*-****************************************************************************
|
||||||
|
* Experimental section
|
||||||
|
*
|
||||||
|
* Symbols declared in this section must be considered unstable. Their
|
||||||
|
* signatures or semantics may change, or they may be removed altogether in the
|
||||||
|
* future. They are therefore only safe to depend on when the caller is
|
||||||
|
* statically linked against the library.
|
||||||
|
*
|
||||||
|
* To protect against unsafe usage, not only are the declarations guarded,
|
||||||
|
* the definitions are hidden by default
|
||||||
|
* when building LZ4 as a shared/dynamic library.
|
||||||
|
*
|
||||||
|
* In order to access these declarations,
|
||||||
|
* define LZ4_STATIC_LINKING_ONLY in your application
|
||||||
|
* before including LZ4's headers.
|
||||||
|
*
|
||||||
|
* In order to make their implementations accessible dynamically, you must
|
||||||
|
* define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef LZ4_STATIC_LINKING_ONLY
|
||||||
|
|
||||||
|
#ifndef LZ4_STATIC_3504398509
|
||||||
|
#define LZ4_STATIC_3504398509
|
||||||
|
|
||||||
|
#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS
|
||||||
|
#define LZ4LIB_STATIC_API LZ4LIB_API
|
||||||
|
#else
|
||||||
|
#define LZ4LIB_STATIC_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_compress_fast_extState_fastReset() :
|
||||||
|
* A variant of LZ4_compress_fast_extState().
|
||||||
|
*
|
||||||
|
* Using this variant avoids an expensive initialization step.
|
||||||
|
* It is only safe to call if the state buffer is known to be correctly initialized already
|
||||||
|
* (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized").
|
||||||
|
* From a high level, the difference is that
|
||||||
|
* this function initializes the provided state with a call to something like LZ4_resetStream_fast()
|
||||||
|
* while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream().
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||||
|
|
||||||
|
/*! LZ4_attach_dictionary() :
|
||||||
|
* This is an experimental API that allows
|
||||||
|
* efficient use of a static dictionary many times.
|
||||||
|
*
|
||||||
|
* Rather than re-loading the dictionary buffer into a working context before
|
||||||
|
* each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a
|
||||||
|
* working LZ4_stream_t, this function introduces a no-copy setup mechanism,
|
||||||
|
* in which the working stream references the dictionary stream in-place.
|
||||||
|
*
|
||||||
|
* Several assumptions are made about the state of the dictionary stream.
|
||||||
|
* Currently, only streams which have been prepared by LZ4_loadDict() should
|
||||||
|
* be expected to work.
|
||||||
|
*
|
||||||
|
* Alternatively, the provided dictionaryStream may be NULL,
|
||||||
|
* in which case any existing dictionary stream is unset.
|
||||||
|
*
|
||||||
|
* If a dictionary is provided, it replaces any pre-existing stream history.
|
||||||
|
* The dictionary contents are the only history that can be referenced and
|
||||||
|
* logically immediately precede the data compressed in the first subsequent
|
||||||
|
* compression call.
|
||||||
|
*
|
||||||
|
* The dictionary will only remain attached to the working stream through the
|
||||||
|
* first compression call, at the end of which it is cleared. The dictionary
|
||||||
|
* stream (and source buffer) must remain in-place / accessible / unchanged
|
||||||
|
* through the completion of the first compression call on the stream.
|
||||||
|
*/
|
||||||
|
LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream);
|
||||||
|
|
||||||
|
|
||||||
|
/*! In-place compression and decompression
|
||||||
|
*
|
||||||
|
* It's possible to have input and output sharing the same buffer,
|
||||||
|
* for highly constrained memory environments.
|
||||||
|
* In both cases, it requires input to lay at the end of the buffer,
|
||||||
|
* and decompression to start at beginning of the buffer.
|
||||||
|
* Buffer size must feature some margin, hence be larger than final size.
|
||||||
|
*
|
||||||
|
* |<------------------------buffer--------------------------------->|
|
||||||
|
* |<-----------compressed data--------->|
|
||||||
|
* |<-----------decompressed size------------------>|
|
||||||
|
* |<----margin---->|
|
||||||
|
*
|
||||||
|
* This technique is more useful for decompression,
|
||||||
|
* since decompressed size is typically larger,
|
||||||
|
* and margin is short.
|
||||||
|
*
|
||||||
|
* In-place decompression will work inside any buffer
|
||||||
|
* which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).
|
||||||
|
* This presumes that decompressedSize > compressedSize.
|
||||||
|
* Otherwise, it means compression actually expanded data,
|
||||||
|
* and it would be more efficient to store such data with a flag indicating it's not compressed.
|
||||||
|
* This can happen when data is not compressible (already compressed, or encrypted).
|
||||||
|
*
|
||||||
|
* For in-place compression, margin is larger, as it must be able to cope with both
|
||||||
|
* history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,
|
||||||
|
* and data expansion, which can happen when input is not compressible.
|
||||||
|
* As a consequence, buffer size requirements are much higher,
|
||||||
|
* and memory savings offered by in-place compression are more limited.
|
||||||
|
*
|
||||||
|
* There are ways to limit this cost for compression :
|
||||||
|
* - Reduce history size, by modifying LZ4_DISTANCE_MAX.
|
||||||
|
* Note that it is a compile-time constant, so all compressions will apply this limit.
|
||||||
|
* Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,
|
||||||
|
* so it's a reasonable trick when inputs are known to be small.
|
||||||
|
* - Require the compressor to deliver a "maximum compressed size".
|
||||||
|
* This is the `dstCapacity` parameter in `LZ4_compress*()`.
|
||||||
|
* When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,
|
||||||
|
* in which case, the return code will be 0 (zero).
|
||||||
|
* The caller must be ready for these cases to happen,
|
||||||
|
* and typically design a backup scheme to send data uncompressed.
|
||||||
|
* The combination of both techniques can significantly reduce
|
||||||
|
* the amount of margin required for in-place compression.
|
||||||
|
*
|
||||||
|
* In-place compression can work in any buffer
|
||||||
|
* which size is >= (maxCompressedSize)
|
||||||
|
* with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.
|
||||||
|
* LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,
|
||||||
|
* so it's possible to reduce memory requirements by playing with them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32)
|
||||||
|
#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */
|
||||||
|
|
||||||
|
#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */
|
||||||
|
# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */
|
||||||
|
#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */
|
||||||
|
|
||||||
|
#endif /* LZ4_STATIC_3504398509 */
|
||||||
|
#endif /* LZ4_STATIC_LINKING_ONLY */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LZ4_H_98237428734687
|
||||||
|
#define LZ4_H_98237428734687
|
||||||
|
|
||||||
|
/*-************************************************************
|
||||||
|
* Private Definitions
|
||||||
|
**************************************************************
|
||||||
|
* Do not use these definitions directly.
|
||||||
|
* They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
|
||||||
|
* Accessing members will expose user code to API and/or ABI break in future versions of the library.
|
||||||
|
**************************************************************/
|
||||||
|
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
|
||||||
|
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
|
||||||
|
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
|
||||||
|
|
||||||
|
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||||
|
# include <stdint.h>
|
||||||
|
typedef int8_t LZ4_i8;
|
||||||
|
typedef uint8_t LZ4_byte;
|
||||||
|
typedef uint16_t LZ4_u16;
|
||||||
|
typedef uint32_t LZ4_u32;
|
||||||
|
#else
|
||||||
|
typedef signed char LZ4_i8;
|
||||||
|
typedef unsigned char LZ4_byte;
|
||||||
|
typedef unsigned short LZ4_u16;
|
||||||
|
typedef unsigned int LZ4_u32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
||||||
|
struct LZ4_stream_t_internal {
|
||||||
|
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
|
||||||
|
LZ4_u32 currentOffset;
|
||||||
|
LZ4_u32 tableType;
|
||||||
|
const LZ4_byte* dictionary;
|
||||||
|
const LZ4_stream_t_internal* dictCtx;
|
||||||
|
LZ4_u32 dictSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const LZ4_byte* externalDict;
|
||||||
|
size_t extDictSize;
|
||||||
|
const LZ4_byte* prefixEnd;
|
||||||
|
size_t prefixSize;
|
||||||
|
} LZ4_streamDecode_t_internal;
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_stream_t :
|
||||||
|
* Do not use below internal definitions directly !
|
||||||
|
* Declare or allocate an LZ4_stream_t instead.
|
||||||
|
* LZ4_stream_t can also be created using LZ4_createStream(), which is recommended.
|
||||||
|
* The structure definition can be convenient for static allocation
|
||||||
|
* (on stack, or as part of larger structure).
|
||||||
|
* Init this structure with LZ4_initStream() before first use.
|
||||||
|
* note : only use this definition in association with static linking !
|
||||||
|
* this definition is not API/ABI safe, and may change in future versions.
|
||||||
|
*/
|
||||||
|
#define LZ4_STREAMSIZE ((1UL << LZ4_MEMORY_USAGE) + 32) /* static size, for inter-version compatibility */
|
||||||
|
#define LZ4_STREAMSIZE_VOIDP (LZ4_STREAMSIZE / sizeof(void*))
|
||||||
|
union LZ4_stream_u {
|
||||||
|
void* table[LZ4_STREAMSIZE_VOIDP];
|
||||||
|
LZ4_stream_t_internal internal_donotuse;
|
||||||
|
}; /* previously typedef'd to LZ4_stream_t */
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_initStream() : v1.9.0+
|
||||||
|
* An LZ4_stream_t structure must be initialized at least once.
|
||||||
|
* This is automatically done when invoking LZ4_createStream(),
|
||||||
|
* but it's not when the structure is simply declared on stack (for example).
|
||||||
|
*
|
||||||
|
* Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t.
|
||||||
|
* It can also initialize any arbitrary buffer of sufficient size,
|
||||||
|
* and will @return a pointer of proper type upon initialization.
|
||||||
|
*
|
||||||
|
* Note : initialization fails if size and alignment conditions are not respected.
|
||||||
|
* In which case, the function will @return NULL.
|
||||||
|
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
|
||||||
|
* Note3: Before v1.9.0, use LZ4_resetStream() instead
|
||||||
|
*/
|
||||||
|
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
/*! LZ4_streamDecode_t :
|
||||||
|
* information structure to track an LZ4 stream during decompression.
|
||||||
|
* init this structure using LZ4_setStreamDecode() before first use.
|
||||||
|
* note : only use in association with static linking !
|
||||||
|
* this definition is not API/ABI safe,
|
||||||
|
* and may change in a future version !
|
||||||
|
*/
|
||||||
|
#define LZ4_STREAMDECODESIZE_U64 (4 + ((sizeof(void*)==16) ? 2 : 0) /*AS-400*/ )
|
||||||
|
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
|
||||||
|
union LZ4_streamDecode_u {
|
||||||
|
unsigned long long table[LZ4_STREAMDECODESIZE_U64];
|
||||||
|
LZ4_streamDecode_t_internal internal_donotuse;
|
||||||
|
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-************************************
|
||||||
|
* Obsolete Functions
|
||||||
|
**************************************/
|
||||||
|
|
||||||
|
/*! Deprecation warnings
|
||||||
|
*
|
||||||
|
* Deprecated functions make the compiler generate a warning when invoked.
|
||||||
|
* This is meant to invite users to update their source code.
|
||||||
|
* Should deprecation warnings be a problem, it is generally possible to disable them,
|
||||||
|
* typically with -Wno-deprecated-declarations for gcc
|
||||||
|
* or _CRT_SECURE_NO_WARNINGS in Visual.
|
||||||
|
*
|
||||||
|
* Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
* before including the header file.
|
||||||
|
*/
|
||||||
|
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
|
||||||
|
#else
|
||||||
|
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||||
|
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
|
# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))
|
||||||
|
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
|
# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)
|
||||||
|
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
|
||||||
|
# else
|
||||||
|
# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")
|
||||||
|
# define LZ4_DEPRECATED(message) /* disabled */
|
||||||
|
# endif
|
||||||
|
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
|
||||||
|
|
||||||
|
/*! Obsolete compression functions (since v1.7.3) */
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||||
|
|
||||||
|
/*! Obsolete decompression functions (since v1.8.0) */
|
||||||
|
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
|
||||||
|
|
||||||
|
/* Obsolete streaming functions (since v1.7.0)
|
||||||
|
* degraded functionality; do not use!
|
||||||
|
*
|
||||||
|
* In order to perform streaming compression, these functions depended on data
|
||||||
|
* that is no longer tracked in the state. They have been preserved as well as
|
||||||
|
* possible: using them will still produce a correct output. However, they don't
|
||||||
|
* actually retain any history between compression calls. The compression ratio
|
||||||
|
* achieved will therefore be no better than compressing each chunk
|
||||||
|
* independently.
|
||||||
|
*/
|
||||||
|
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);
|
||||||
|
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);
|
||||||
|
LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
|
||||||
|
LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
|
||||||
|
|
||||||
|
/*! Obsolete streaming decoding functions (since v1.7.0) */
|
||||||
|
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
||||||
|
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
||||||
|
|
||||||
|
/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :
|
||||||
|
* These functions used to be faster than LZ4_decompress_safe(),
|
||||||
|
* but this is no longer the case. They are now slower.
|
||||||
|
* This is because LZ4_decompress_fast() doesn't know the input size,
|
||||||
|
* and therefore must progress more cautiously into the input buffer to not read beyond the end of block.
|
||||||
|
* On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.
|
||||||
|
* As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.
|
||||||
|
*
|
||||||
|
* The last remaining LZ4_decompress_fast() specificity is that
|
||||||
|
* it can decompress a block without knowing its compressed size.
|
||||||
|
* Such functionality can be achieved in a more secure manner
|
||||||
|
* by employing LZ4_decompress_safe_partial().
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* originalSize : is the uncompressed size to regenerate.
|
||||||
|
* `dst` must be already allocated, its size must be >= 'originalSize' bytes.
|
||||||
|
* @return : number of bytes read from source buffer (== compressed size).
|
||||||
|
* The function expects to finish at block's end exactly.
|
||||||
|
* If the source stream is detected malformed, the function stops decoding and returns a negative result.
|
||||||
|
* note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer.
|
||||||
|
* However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds.
|
||||||
|
* Also, since match offsets are not validated, match reads from 'src' may underflow too.
|
||||||
|
* These issues never happen if input (compressed) data is correct.
|
||||||
|
* But they may happen if input data is invalid (error or intentional tampering).
|
||||||
|
* As a consequence, use these functions in trusted environments with trusted data **only**.
|
||||||
|
*/
|
||||||
|
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")
|
||||||
|
LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
|
||||||
|
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
|
||||||
|
LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
|
||||||
|
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead")
|
||||||
|
LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
|
||||||
|
|
||||||
|
/*! LZ4_resetStream() :
|
||||||
|
* An LZ4_stream_t structure must be initialized at least once.
|
||||||
|
* This is done with LZ4_initStream(), or LZ4_resetStream().
|
||||||
|
* Consider switching to LZ4_initStream(),
|
||||||
|
* invoking LZ4_resetStream() will trigger deprecation warnings in the future.
|
||||||
|
*/
|
||||||
|
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* LZ4_H_98237428734687 */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
2961
rres/external/monocypher.c
vendored
Normal file
2961
rres/external/monocypher.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
321
rres/external/monocypher.h
vendored
Normal file
321
rres/external/monocypher.h
vendored
Normal file
|
@ -0,0 +1,321 @@
|
||||||
|
// Monocypher version 4.0.1
|
||||||
|
//
|
||||||
|
// This file is dual-licensed. Choose whichever licence you want from
|
||||||
|
// the two licences listed below.
|
||||||
|
//
|
||||||
|
// The first licence is a regular 2-clause BSD licence. The second licence
|
||||||
|
// is the CC-0 from Creative Commons. It is intended to release Monocypher
|
||||||
|
// to the public domain. The BSD licence serves as a fallback option.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017-2019, Loup Vaillant
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Written in 2017-2019 by Loup Vaillant
|
||||||
|
//
|
||||||
|
// To the extent possible under law, the author(s) have dedicated all copyright
|
||||||
|
// and related neighboring rights to this software to the public domain
|
||||||
|
// worldwide. This software is distributed without any warranty.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the CC0 Public Domain Dedication along
|
||||||
|
// with this software. If not, see
|
||||||
|
// <https://creativecommons.org/publicdomain/zero/1.0/>
|
||||||
|
|
||||||
|
#ifndef MONOCYPHER_H
|
||||||
|
#define MONOCYPHER_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef MONOCYPHER_CPP_NAMESPACE
|
||||||
|
namespace MONOCYPHER_CPP_NAMESPACE {
|
||||||
|
#elif defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Constant time comparisons
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
// Return 0 if a and b are equal, -1 otherwise
|
||||||
|
int crypto_verify16(const uint8_t a[16], const uint8_t b[16]);
|
||||||
|
int crypto_verify32(const uint8_t a[32], const uint8_t b[32]);
|
||||||
|
int crypto_verify64(const uint8_t a[64], const uint8_t b[64]);
|
||||||
|
|
||||||
|
|
||||||
|
// Erase sensitive data
|
||||||
|
// --------------------
|
||||||
|
void crypto_wipe(void *secret, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
// Authenticated encryption
|
||||||
|
// ------------------------
|
||||||
|
void crypto_aead_lock(uint8_t *cipher_text,
|
||||||
|
uint8_t mac [16],
|
||||||
|
const uint8_t key [32],
|
||||||
|
const uint8_t nonce[24],
|
||||||
|
const uint8_t *ad, size_t ad_size,
|
||||||
|
const uint8_t *plain_text, size_t text_size);
|
||||||
|
int crypto_aead_unlock(uint8_t *plain_text,
|
||||||
|
const uint8_t mac [16],
|
||||||
|
const uint8_t key [32],
|
||||||
|
const uint8_t nonce[24],
|
||||||
|
const uint8_t *ad, size_t ad_size,
|
||||||
|
const uint8_t *cipher_text, size_t text_size);
|
||||||
|
|
||||||
|
// Authenticated stream
|
||||||
|
// --------------------
|
||||||
|
typedef struct {
|
||||||
|
uint64_t counter;
|
||||||
|
uint8_t key[32];
|
||||||
|
uint8_t nonce[8];
|
||||||
|
} crypto_aead_ctx;
|
||||||
|
|
||||||
|
void crypto_aead_init_x(crypto_aead_ctx *ctx,
|
||||||
|
const uint8_t key[32], const uint8_t nonce[24]);
|
||||||
|
void crypto_aead_init_djb(crypto_aead_ctx *ctx,
|
||||||
|
const uint8_t key[32], const uint8_t nonce[8]);
|
||||||
|
void crypto_aead_init_ietf(crypto_aead_ctx *ctx,
|
||||||
|
const uint8_t key[32], const uint8_t nonce[12]);
|
||||||
|
|
||||||
|
void crypto_aead_write(crypto_aead_ctx *ctx,
|
||||||
|
uint8_t *cipher_text,
|
||||||
|
uint8_t mac[16],
|
||||||
|
const uint8_t *ad , size_t ad_size,
|
||||||
|
const uint8_t *plain_text, size_t text_size);
|
||||||
|
int crypto_aead_read(crypto_aead_ctx *ctx,
|
||||||
|
uint8_t *plain_text,
|
||||||
|
const uint8_t mac[16],
|
||||||
|
const uint8_t *ad , size_t ad_size,
|
||||||
|
const uint8_t *cipher_text, size_t text_size);
|
||||||
|
|
||||||
|
|
||||||
|
// General purpose hash (BLAKE2b)
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
// Direct interface
|
||||||
|
void crypto_blake2b(uint8_t *hash, size_t hash_size,
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
|
||||||
|
void crypto_blake2b_keyed(uint8_t *hash, size_t hash_size,
|
||||||
|
const uint8_t *key, size_t key_size,
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
|
||||||
|
// Incremental interface
|
||||||
|
typedef struct {
|
||||||
|
// Do not rely on the size or contents of this type,
|
||||||
|
// for they may change without notice.
|
||||||
|
uint64_t hash[8];
|
||||||
|
uint64_t input_offset[2];
|
||||||
|
uint64_t input[16];
|
||||||
|
size_t input_idx;
|
||||||
|
size_t hash_size;
|
||||||
|
} crypto_blake2b_ctx;
|
||||||
|
|
||||||
|
void crypto_blake2b_init(crypto_blake2b_ctx *ctx, size_t hash_size);
|
||||||
|
void crypto_blake2b_keyed_init(crypto_blake2b_ctx *ctx, size_t hash_size,
|
||||||
|
const uint8_t *key, size_t key_size);
|
||||||
|
void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
void crypto_blake2b_final(crypto_blake2b_ctx *ctx, uint8_t *hash);
|
||||||
|
|
||||||
|
|
||||||
|
// Password key derivation (Argon2)
|
||||||
|
// --------------------------------
|
||||||
|
#define CRYPTO_ARGON2_D 0
|
||||||
|
#define CRYPTO_ARGON2_I 1
|
||||||
|
#define CRYPTO_ARGON2_ID 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t algorithm; // Argon2d, Argon2i, Argon2id
|
||||||
|
uint32_t nb_blocks; // memory hardness, >= 8 * nb_lanes
|
||||||
|
uint32_t nb_passes; // CPU hardness, >= 1 (>= 3 recommended for Argon2i)
|
||||||
|
uint32_t nb_lanes; // parallelism level (single threaded anyway)
|
||||||
|
} crypto_argon2_config;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const uint8_t *pass;
|
||||||
|
const uint8_t *salt;
|
||||||
|
uint32_t pass_size;
|
||||||
|
uint32_t salt_size; // 16 bytes recommended
|
||||||
|
} crypto_argon2_inputs;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const uint8_t *key; // may be NULL if no key
|
||||||
|
const uint8_t *ad; // may be NULL if no additional data
|
||||||
|
uint32_t key_size; // 0 if no key (32 bytes recommended otherwise)
|
||||||
|
uint32_t ad_size; // 0 if no additional data
|
||||||
|
} crypto_argon2_extras;
|
||||||
|
|
||||||
|
extern const crypto_argon2_extras crypto_argon2_no_extras;
|
||||||
|
|
||||||
|
void crypto_argon2(uint8_t *hash, uint32_t hash_size, void *work_area,
|
||||||
|
crypto_argon2_config config,
|
||||||
|
crypto_argon2_inputs inputs,
|
||||||
|
crypto_argon2_extras extras);
|
||||||
|
|
||||||
|
|
||||||
|
// Key exchange (X-25519)
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
// Shared secrets are not quite random.
|
||||||
|
// Hash them to derive an actual shared key.
|
||||||
|
void crypto_x25519_public_key(uint8_t public_key[32],
|
||||||
|
const uint8_t secret_key[32]);
|
||||||
|
void crypto_x25519(uint8_t raw_shared_secret[32],
|
||||||
|
const uint8_t your_secret_key [32],
|
||||||
|
const uint8_t their_public_key [32]);
|
||||||
|
|
||||||
|
// Conversion to EdDSA
|
||||||
|
void crypto_x25519_to_eddsa(uint8_t eddsa[32], const uint8_t x25519[32]);
|
||||||
|
|
||||||
|
// scalar "division"
|
||||||
|
// Used for OPRF. Be aware that exponential blinding is less secure
|
||||||
|
// than Diffie-Hellman key exchange.
|
||||||
|
void crypto_x25519_inverse(uint8_t blind_salt [32],
|
||||||
|
const uint8_t private_key[32],
|
||||||
|
const uint8_t curve_point[32]);
|
||||||
|
|
||||||
|
// "Dirty" versions of x25519_public_key().
|
||||||
|
// Use with crypto_elligator_rev().
|
||||||
|
// Leaks 3 bits of the private key.
|
||||||
|
void crypto_x25519_dirty_small(uint8_t pk[32], const uint8_t sk[32]);
|
||||||
|
void crypto_x25519_dirty_fast (uint8_t pk[32], const uint8_t sk[32]);
|
||||||
|
|
||||||
|
|
||||||
|
// Signatures
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
// EdDSA with curve25519 + BLAKE2b
|
||||||
|
void crypto_eddsa_key_pair(uint8_t secret_key[64],
|
||||||
|
uint8_t public_key[32],
|
||||||
|
uint8_t seed[32]);
|
||||||
|
void crypto_eddsa_sign(uint8_t signature [64],
|
||||||
|
const uint8_t secret_key[64],
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
int crypto_eddsa_check(const uint8_t signature [64],
|
||||||
|
const uint8_t public_key[32],
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
|
||||||
|
// Conversion to X25519
|
||||||
|
void crypto_eddsa_to_x25519(uint8_t x25519[32], const uint8_t eddsa[32]);
|
||||||
|
|
||||||
|
// EdDSA building blocks
|
||||||
|
void crypto_eddsa_trim_scalar(uint8_t out[32], const uint8_t in[32]);
|
||||||
|
void crypto_eddsa_reduce(uint8_t reduced[32], const uint8_t expanded[64]);
|
||||||
|
void crypto_eddsa_mul_add(uint8_t r[32],
|
||||||
|
const uint8_t a[32],
|
||||||
|
const uint8_t b[32],
|
||||||
|
const uint8_t c[32]);
|
||||||
|
void crypto_eddsa_scalarbase(uint8_t point[32], const uint8_t scalar[32]);
|
||||||
|
int crypto_eddsa_check_equation(const uint8_t signature[64],
|
||||||
|
const uint8_t public_key[32],
|
||||||
|
const uint8_t h_ram[32]);
|
||||||
|
|
||||||
|
|
||||||
|
// Chacha20
|
||||||
|
// --------
|
||||||
|
|
||||||
|
// Specialised hash.
|
||||||
|
// Used to hash X25519 shared secrets.
|
||||||
|
void crypto_chacha20_h(uint8_t out[32],
|
||||||
|
const uint8_t key[32],
|
||||||
|
const uint8_t in [16]);
|
||||||
|
|
||||||
|
// Unauthenticated stream cipher.
|
||||||
|
// Don't forget to add authentication.
|
||||||
|
uint64_t crypto_chacha20_djb(uint8_t *cipher_text,
|
||||||
|
const uint8_t *plain_text,
|
||||||
|
size_t text_size,
|
||||||
|
const uint8_t key[32],
|
||||||
|
const uint8_t nonce[8],
|
||||||
|
uint64_t ctr);
|
||||||
|
uint32_t crypto_chacha20_ietf(uint8_t *cipher_text,
|
||||||
|
const uint8_t *plain_text,
|
||||||
|
size_t text_size,
|
||||||
|
const uint8_t key[32],
|
||||||
|
const uint8_t nonce[12],
|
||||||
|
uint32_t ctr);
|
||||||
|
uint64_t crypto_chacha20_x(uint8_t *cipher_text,
|
||||||
|
const uint8_t *plain_text,
|
||||||
|
size_t text_size,
|
||||||
|
const uint8_t key[32],
|
||||||
|
const uint8_t nonce[24],
|
||||||
|
uint64_t ctr);
|
||||||
|
|
||||||
|
|
||||||
|
// Poly 1305
|
||||||
|
// ---------
|
||||||
|
|
||||||
|
// This is a *one time* authenticator.
|
||||||
|
// Disclosing the mac reveals the key.
|
||||||
|
// See crypto_lock() on how to use it properly.
|
||||||
|
|
||||||
|
// Direct interface
|
||||||
|
void crypto_poly1305(uint8_t mac[16],
|
||||||
|
const uint8_t *message, size_t message_size,
|
||||||
|
const uint8_t key[32]);
|
||||||
|
|
||||||
|
// Incremental interface
|
||||||
|
typedef struct {
|
||||||
|
// Do not rely on the size or contents of this type,
|
||||||
|
// for they may change without notice.
|
||||||
|
uint8_t c[16]; // chunk of the message
|
||||||
|
size_t c_idx; // How many bytes are there in the chunk.
|
||||||
|
uint32_t r [4]; // constant multiplier (from the secret key)
|
||||||
|
uint32_t pad[4]; // random number added at the end (from the secret key)
|
||||||
|
uint32_t h [5]; // accumulated hash
|
||||||
|
} crypto_poly1305_ctx;
|
||||||
|
|
||||||
|
void crypto_poly1305_init (crypto_poly1305_ctx *ctx, const uint8_t key[32]);
|
||||||
|
void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
|
||||||
|
const uint8_t *message, size_t message_size);
|
||||||
|
void crypto_poly1305_final (crypto_poly1305_ctx *ctx, uint8_t mac[16]);
|
||||||
|
|
||||||
|
|
||||||
|
// Elligator 2
|
||||||
|
// -----------
|
||||||
|
|
||||||
|
// Elligator mappings proper
|
||||||
|
void crypto_elligator_map(uint8_t curve [32], const uint8_t hidden[32]);
|
||||||
|
int crypto_elligator_rev(uint8_t hidden[32], const uint8_t curve [32],
|
||||||
|
uint8_t tweak);
|
||||||
|
|
||||||
|
// Easy to use key pair generation
|
||||||
|
void crypto_elligator_key_pair(uint8_t hidden[32], uint8_t secret_key[32],
|
||||||
|
uint8_t seed[32]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MONOCYPHER_H
|
671
rres/external/qoi.h
vendored
Normal file
671
rres/external/qoi.h
vendored
Normal file
|
@ -0,0 +1,671 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
QOI - The "Quite OK Image" format for fast, lossless image compression
|
||||||
|
|
||||||
|
Dominic Szablewski - https://phoboslab.org
|
||||||
|
|
||||||
|
|
||||||
|
-- LICENSE: The MIT License(MIT)
|
||||||
|
|
||||||
|
Copyright(c) 2021 Dominic Szablewski
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files(the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions :
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
-- About
|
||||||
|
|
||||||
|
QOI encodes and decodes images in a lossless format. Compared to stb_image and
|
||||||
|
stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and
|
||||||
|
20% better compression.
|
||||||
|
|
||||||
|
|
||||||
|
-- Synopsis
|
||||||
|
|
||||||
|
// Define `QOI_IMPLEMENTATION` in *one* C/C++ file before including this
|
||||||
|
// library to create the implementation.
|
||||||
|
|
||||||
|
#define QOI_IMPLEMENTATION
|
||||||
|
#include "qoi.h"
|
||||||
|
|
||||||
|
// Encode and store an RGBA buffer to the file system. The qoi_desc describes
|
||||||
|
// the input pixel data.
|
||||||
|
qoi_write("image_new.qoi", rgba_pixels, &(qoi_desc){
|
||||||
|
.width = 1920,
|
||||||
|
.height = 1080,
|
||||||
|
.channels = 4,
|
||||||
|
.colorspace = QOI_SRGB
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load and decode a QOI image from the file system into a 32bbp RGBA buffer.
|
||||||
|
// The qoi_desc struct will be filled with the width, height, number of channels
|
||||||
|
// and colorspace read from the file header.
|
||||||
|
qoi_desc desc;
|
||||||
|
void *rgba_pixels = qoi_read("image.qoi", &desc, 4);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Documentation
|
||||||
|
|
||||||
|
This library provides the following functions;
|
||||||
|
- qoi_read -- read and decode a QOI file
|
||||||
|
- qoi_decode -- decode the raw bytes of a QOI image from memory
|
||||||
|
- qoi_write -- encode and write a QOI file
|
||||||
|
- qoi_encode -- encode an rgba buffer into a QOI image in memory
|
||||||
|
|
||||||
|
See the function declaration below for the signature and more information.
|
||||||
|
|
||||||
|
If you don't want/need the qoi_read and qoi_write functions, you can define
|
||||||
|
QOI_NO_STDIO before including this library.
|
||||||
|
|
||||||
|
This library uses malloc() and free(). To supply your own malloc implementation
|
||||||
|
you can define QOI_MALLOC and QOI_FREE before including this library.
|
||||||
|
|
||||||
|
This library uses memset() to zero-initialize the index. To supply your own
|
||||||
|
implementation you can define QOI_ZEROARR before including this library.
|
||||||
|
|
||||||
|
|
||||||
|
-- Data Format
|
||||||
|
|
||||||
|
A QOI file has a 14 byte header, followed by any number of data "chunks" and an
|
||||||
|
8-byte end marker.
|
||||||
|
|
||||||
|
struct qoi_header_t {
|
||||||
|
char magic[4]; // magic bytes "qoif"
|
||||||
|
uint32_t width; // image width in pixels (BE)
|
||||||
|
uint32_t height; // image height in pixels (BE)
|
||||||
|
uint8_t channels; // 3 = RGB, 4 = RGBA
|
||||||
|
uint8_t colorspace; // 0 = sRGB with linear alpha, 1 = all channels linear
|
||||||
|
};
|
||||||
|
|
||||||
|
Images are encoded row by row, left to right, top to bottom. The decoder and
|
||||||
|
encoder start with {r: 0, g: 0, b: 0, a: 255} as the previous pixel value. An
|
||||||
|
image is complete when all pixels specified by width * height have been covered.
|
||||||
|
|
||||||
|
Pixels are encoded as
|
||||||
|
- a run of the previous pixel
|
||||||
|
- an index into an array of previously seen pixels
|
||||||
|
- a difference to the previous pixel value in r,g,b
|
||||||
|
- full r,g,b or r,g,b,a values
|
||||||
|
|
||||||
|
The color channels are assumed to not be premultiplied with the alpha channel
|
||||||
|
("un-premultiplied alpha").
|
||||||
|
|
||||||
|
A running array[64] (zero-initialized) of previously seen pixel values is
|
||||||
|
maintained by the encoder and decoder. Each pixel that is seen by the encoder
|
||||||
|
and decoder is put into this array at the position formed by a hash function of
|
||||||
|
the color value. In the encoder, if the pixel value at the index matches the
|
||||||
|
current pixel, this index position is written to the stream as QOI_OP_INDEX.
|
||||||
|
The hash function for the index is:
|
||||||
|
|
||||||
|
index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64
|
||||||
|
|
||||||
|
Each chunk starts with a 2- or 8-bit tag, followed by a number of data bits. The
|
||||||
|
bit length of chunks is divisible by 8 - i.e. all chunks are byte aligned. All
|
||||||
|
values encoded in these data bits have the most significant bit on the left.
|
||||||
|
|
||||||
|
The 8-bit tags have precedence over the 2-bit tags. A decoder must check for the
|
||||||
|
presence of an 8-bit tag first.
|
||||||
|
|
||||||
|
The byte stream's end is marked with 7 0x00 bytes followed a single 0x01 byte.
|
||||||
|
|
||||||
|
|
||||||
|
The possible chunks are:
|
||||||
|
|
||||||
|
|
||||||
|
.- QOI_OP_INDEX ----------.
|
||||||
|
| Byte[0] |
|
||||||
|
| 7 6 5 4 3 2 1 0 |
|
||||||
|
|-------+-----------------|
|
||||||
|
| 0 0 | index |
|
||||||
|
`-------------------------`
|
||||||
|
2-bit tag b00
|
||||||
|
6-bit index into the color index array: 0..63
|
||||||
|
|
||||||
|
A valid encoder must not issue 2 or more consecutive QOI_OP_INDEX chunks to the
|
||||||
|
same index. QOI_OP_RUN should be used instead.
|
||||||
|
|
||||||
|
|
||||||
|
.- QOI_OP_DIFF -----------.
|
||||||
|
| Byte[0] |
|
||||||
|
| 7 6 5 4 3 2 1 0 |
|
||||||
|
|-------+-----+-----+-----|
|
||||||
|
| 0 1 | dr | dg | db |
|
||||||
|
`-------------------------`
|
||||||
|
2-bit tag b01
|
||||||
|
2-bit red channel difference from the previous pixel between -2..1
|
||||||
|
2-bit green channel difference from the previous pixel between -2..1
|
||||||
|
2-bit blue channel difference from the previous pixel between -2..1
|
||||||
|
|
||||||
|
The difference to the current channel values are using a wraparound operation,
|
||||||
|
so "1 - 2" will result in 255, while "255 + 1" will result in 0.
|
||||||
|
|
||||||
|
Values are stored as unsigned integers with a bias of 2. E.g. -2 is stored as
|
||||||
|
0 (b00). 1 is stored as 3 (b11).
|
||||||
|
|
||||||
|
The alpha value remains unchanged from the previous pixel.
|
||||||
|
|
||||||
|
|
||||||
|
.- QOI_OP_LUMA -------------------------------------.
|
||||||
|
| Byte[0] | Byte[1] |
|
||||||
|
| 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 |
|
||||||
|
|-------+-----------------+-------------+-----------|
|
||||||
|
| 1 0 | green diff | dr - dg | db - dg |
|
||||||
|
`---------------------------------------------------`
|
||||||
|
2-bit tag b10
|
||||||
|
6-bit green channel difference from the previous pixel -32..31
|
||||||
|
4-bit red channel difference minus green channel difference -8..7
|
||||||
|
4-bit blue channel difference minus green channel difference -8..7
|
||||||
|
|
||||||
|
The green channel is used to indicate the general direction of change and is
|
||||||
|
encoded in 6 bits. The red and blue channels (dr and db) base their diffs off
|
||||||
|
of the green channel difference and are encoded in 4 bits. I.e.:
|
||||||
|
dr_dg = (cur_px.r - prev_px.r) - (cur_px.g - prev_px.g)
|
||||||
|
db_dg = (cur_px.b - prev_px.b) - (cur_px.g - prev_px.g)
|
||||||
|
|
||||||
|
The difference to the current channel values are using a wraparound operation,
|
||||||
|
so "10 - 13" will result in 253, while "250 + 7" will result in 1.
|
||||||
|
|
||||||
|
Values are stored as unsigned integers with a bias of 32 for the green channel
|
||||||
|
and a bias of 8 for the red and blue channel.
|
||||||
|
|
||||||
|
The alpha value remains unchanged from the previous pixel.
|
||||||
|
|
||||||
|
|
||||||
|
.- QOI_OP_RUN ------------.
|
||||||
|
| Byte[0] |
|
||||||
|
| 7 6 5 4 3 2 1 0 |
|
||||||
|
|-------+-----------------|
|
||||||
|
| 1 1 | run |
|
||||||
|
`-------------------------`
|
||||||
|
2-bit tag b11
|
||||||
|
6-bit run-length repeating the previous pixel: 1..62
|
||||||
|
|
||||||
|
The run-length is stored with a bias of -1. Note that the run-lengths 63 and 64
|
||||||
|
(b111110 and b111111) are illegal as they are occupied by the QOI_OP_RGB and
|
||||||
|
QOI_OP_RGBA tags.
|
||||||
|
|
||||||
|
|
||||||
|
.- QOI_OP_RGB ------------------------------------------.
|
||||||
|
| Byte[0] | Byte[1] | Byte[2] | Byte[3] |
|
||||||
|
| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 |
|
||||||
|
|-------------------------+---------+---------+---------|
|
||||||
|
| 1 1 1 1 1 1 1 0 | red | green | blue |
|
||||||
|
`-------------------------------------------------------`
|
||||||
|
8-bit tag b11111110
|
||||||
|
8-bit red channel value
|
||||||
|
8-bit green channel value
|
||||||
|
8-bit blue channel value
|
||||||
|
|
||||||
|
The alpha value remains unchanged from the previous pixel.
|
||||||
|
|
||||||
|
|
||||||
|
.- QOI_OP_RGBA ---------------------------------------------------.
|
||||||
|
| Byte[0] | Byte[1] | Byte[2] | Byte[3] | Byte[4] |
|
||||||
|
| 7 6 5 4 3 2 1 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 | 7 .. 0 |
|
||||||
|
|-------------------------+---------+---------+---------+---------|
|
||||||
|
| 1 1 1 1 1 1 1 1 | red | green | blue | alpha |
|
||||||
|
`-----------------------------------------------------------------`
|
||||||
|
8-bit tag b11111111
|
||||||
|
8-bit red channel value
|
||||||
|
8-bit green channel value
|
||||||
|
8-bit blue channel value
|
||||||
|
8-bit alpha channel value
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
Header - Public functions */
|
||||||
|
|
||||||
|
#ifndef QOI_H
|
||||||
|
#define QOI_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* A pointer to a qoi_desc struct has to be supplied to all of qoi's functions.
|
||||||
|
It describes either the input format (for qoi_write and qoi_encode), or is
|
||||||
|
filled with the description read from the file header (for qoi_read and
|
||||||
|
qoi_decode).
|
||||||
|
|
||||||
|
The colorspace in this qoi_desc is an enum where
|
||||||
|
0 = sRGB, i.e. gamma scaled RGB channels and a linear alpha channel
|
||||||
|
1 = all channels are linear
|
||||||
|
You may use the constants QOI_SRGB or QOI_LINEAR. The colorspace is purely
|
||||||
|
informative. It will be saved to the file header, but does not affect
|
||||||
|
how chunks are en-/decoded. */
|
||||||
|
|
||||||
|
#define QOI_SRGB 0
|
||||||
|
#define QOI_LINEAR 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
unsigned char channels;
|
||||||
|
unsigned char colorspace;
|
||||||
|
} qoi_desc;
|
||||||
|
|
||||||
|
#ifndef QOI_NO_STDIO
|
||||||
|
|
||||||
|
/* Encode raw RGB or RGBA pixels into a QOI image and write it to the file
|
||||||
|
system. The qoi_desc struct must be filled with the image width, height,
|
||||||
|
number of channels (3 = RGB, 4 = RGBA) and the colorspace.
|
||||||
|
|
||||||
|
The function returns 0 on failure (invalid parameters, or fopen or malloc
|
||||||
|
failed) or the number of bytes written on success. */
|
||||||
|
|
||||||
|
int qoi_write(const char *filename, const void *data, const qoi_desc *desc);
|
||||||
|
|
||||||
|
|
||||||
|
/* Read and decode a QOI image from the file system. If channels is 0, the
|
||||||
|
number of channels from the file header is used. If channels is 3 or 4 the
|
||||||
|
output format will be forced into this number of channels.
|
||||||
|
|
||||||
|
The function either returns NULL on failure (invalid data, or malloc or fopen
|
||||||
|
failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
|
||||||
|
will be filled with the description from the file header.
|
||||||
|
|
||||||
|
The returned pixel data should be free()d after use. */
|
||||||
|
|
||||||
|
void *qoi_read(const char *filename, qoi_desc *desc, int channels);
|
||||||
|
|
||||||
|
#endif /* QOI_NO_STDIO */
|
||||||
|
|
||||||
|
|
||||||
|
/* Encode raw RGB or RGBA pixels into a QOI image in memory.
|
||||||
|
|
||||||
|
The function either returns NULL on failure (invalid parameters or malloc
|
||||||
|
failed) or a pointer to the encoded data on success. On success the out_len
|
||||||
|
is set to the size in bytes of the encoded data.
|
||||||
|
|
||||||
|
The returned qoi data should be free()d after use. */
|
||||||
|
|
||||||
|
void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len);
|
||||||
|
|
||||||
|
|
||||||
|
/* Decode a QOI image from memory.
|
||||||
|
|
||||||
|
The function either returns NULL on failure (invalid parameters or malloc
|
||||||
|
failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
|
||||||
|
is filled with the description from the file header.
|
||||||
|
|
||||||
|
The returned pixel data should be free()d after use. */
|
||||||
|
|
||||||
|
void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* QOI_H */
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
Implementation */
|
||||||
|
|
||||||
|
#ifdef QOI_IMPLEMENTATION
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef QOI_MALLOC
|
||||||
|
#define QOI_MALLOC(sz) malloc(sz)
|
||||||
|
#define QOI_FREE(p) free(p)
|
||||||
|
#endif
|
||||||
|
#ifndef QOI_ZEROARR
|
||||||
|
#define QOI_ZEROARR(a) memset((a),0,sizeof(a))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define QOI_OP_INDEX 0x00 /* 00xxxxxx */
|
||||||
|
#define QOI_OP_DIFF 0x40 /* 01xxxxxx */
|
||||||
|
#define QOI_OP_LUMA 0x80 /* 10xxxxxx */
|
||||||
|
#define QOI_OP_RUN 0xc0 /* 11xxxxxx */
|
||||||
|
#define QOI_OP_RGB 0xfe /* 11111110 */
|
||||||
|
#define QOI_OP_RGBA 0xff /* 11111111 */
|
||||||
|
|
||||||
|
#define QOI_MASK_2 0xc0 /* 11000000 */
|
||||||
|
|
||||||
|
#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11)
|
||||||
|
#define QOI_MAGIC \
|
||||||
|
(((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \
|
||||||
|
((unsigned int)'i') << 8 | ((unsigned int)'f'))
|
||||||
|
#define QOI_HEADER_SIZE 14
|
||||||
|
|
||||||
|
/* 2GB is the max file size that this implementation can safely handle. We guard
|
||||||
|
against anything larger than that, assuming the worst case with 5 bytes per
|
||||||
|
pixel, rounded down to a nice clean value. 400 million pixels ought to be
|
||||||
|
enough for anybody. */
|
||||||
|
#define QOI_PIXELS_MAX ((unsigned int)400000000)
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct { unsigned char r, g, b, a; } rgba;
|
||||||
|
unsigned int v;
|
||||||
|
} qoi_rgba_t;
|
||||||
|
|
||||||
|
static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1};
|
||||||
|
|
||||||
|
static void qoi_write_32(unsigned char *bytes, int *p, unsigned int v) {
|
||||||
|
bytes[(*p)++] = (0xff000000 & v) >> 24;
|
||||||
|
bytes[(*p)++] = (0x00ff0000 & v) >> 16;
|
||||||
|
bytes[(*p)++] = (0x0000ff00 & v) >> 8;
|
||||||
|
bytes[(*p)++] = (0x000000ff & v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int qoi_read_32(const unsigned char *bytes, int *p) {
|
||||||
|
unsigned int a = bytes[(*p)++];
|
||||||
|
unsigned int b = bytes[(*p)++];
|
||||||
|
unsigned int c = bytes[(*p)++];
|
||||||
|
unsigned int d = bytes[(*p)++];
|
||||||
|
return a << 24 | b << 16 | c << 8 | d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
|
||||||
|
int i, max_size, p, run;
|
||||||
|
int px_len, px_end, px_pos, channels;
|
||||||
|
unsigned char *bytes;
|
||||||
|
const unsigned char *pixels;
|
||||||
|
qoi_rgba_t index[64];
|
||||||
|
qoi_rgba_t px, px_prev;
|
||||||
|
|
||||||
|
if (
|
||||||
|
data == NULL || out_len == NULL || desc == NULL ||
|
||||||
|
desc->width == 0 || desc->height == 0 ||
|
||||||
|
desc->channels < 3 || desc->channels > 4 ||
|
||||||
|
desc->colorspace > 1 ||
|
||||||
|
desc->height >= QOI_PIXELS_MAX / desc->width
|
||||||
|
) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_size =
|
||||||
|
desc->width * desc->height * (desc->channels + 1) +
|
||||||
|
QOI_HEADER_SIZE + sizeof(qoi_padding);
|
||||||
|
|
||||||
|
p = 0;
|
||||||
|
bytes = (unsigned char *) QOI_MALLOC(max_size);
|
||||||
|
if (!bytes) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qoi_write_32(bytes, &p, QOI_MAGIC);
|
||||||
|
qoi_write_32(bytes, &p, desc->width);
|
||||||
|
qoi_write_32(bytes, &p, desc->height);
|
||||||
|
bytes[p++] = desc->channels;
|
||||||
|
bytes[p++] = desc->colorspace;
|
||||||
|
|
||||||
|
|
||||||
|
pixels = (const unsigned char *)data;
|
||||||
|
|
||||||
|
QOI_ZEROARR(index);
|
||||||
|
|
||||||
|
run = 0;
|
||||||
|
px_prev.rgba.r = 0;
|
||||||
|
px_prev.rgba.g = 0;
|
||||||
|
px_prev.rgba.b = 0;
|
||||||
|
px_prev.rgba.a = 255;
|
||||||
|
px = px_prev;
|
||||||
|
|
||||||
|
px_len = desc->width * desc->height * desc->channels;
|
||||||
|
px_end = px_len - desc->channels;
|
||||||
|
channels = desc->channels;
|
||||||
|
|
||||||
|
for (px_pos = 0; px_pos < px_len; px_pos += channels) {
|
||||||
|
if (channels == 4) {
|
||||||
|
px = *(qoi_rgba_t *)(pixels + px_pos);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
px.rgba.r = pixels[px_pos + 0];
|
||||||
|
px.rgba.g = pixels[px_pos + 1];
|
||||||
|
px.rgba.b = pixels[px_pos + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (px.v == px_prev.v) {
|
||||||
|
run++;
|
||||||
|
if (run == 62 || px_pos == px_end) {
|
||||||
|
bytes[p++] = QOI_OP_RUN | (run - 1);
|
||||||
|
run = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int index_pos;
|
||||||
|
|
||||||
|
if (run > 0) {
|
||||||
|
bytes[p++] = QOI_OP_RUN | (run - 1);
|
||||||
|
run = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
index_pos = QOI_COLOR_HASH(px) % 64;
|
||||||
|
|
||||||
|
if (index[index_pos].v == px.v) {
|
||||||
|
bytes[p++] = QOI_OP_INDEX | index_pos;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
index[index_pos] = px;
|
||||||
|
|
||||||
|
if (px.rgba.a == px_prev.rgba.a) {
|
||||||
|
signed char vr = px.rgba.r - px_prev.rgba.r;
|
||||||
|
signed char vg = px.rgba.g - px_prev.rgba.g;
|
||||||
|
signed char vb = px.rgba.b - px_prev.rgba.b;
|
||||||
|
|
||||||
|
signed char vg_r = vr - vg;
|
||||||
|
signed char vg_b = vb - vg;
|
||||||
|
|
||||||
|
if (
|
||||||
|
vr > -3 && vr < 2 &&
|
||||||
|
vg > -3 && vg < 2 &&
|
||||||
|
vb > -3 && vb < 2
|
||||||
|
) {
|
||||||
|
bytes[p++] = QOI_OP_DIFF | (vr + 2) << 4 | (vg + 2) << 2 | (vb + 2);
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
vg_r > -9 && vg_r < 8 &&
|
||||||
|
vg > -33 && vg < 32 &&
|
||||||
|
vg_b > -9 && vg_b < 8
|
||||||
|
) {
|
||||||
|
bytes[p++] = QOI_OP_LUMA | (vg + 32);
|
||||||
|
bytes[p++] = (vg_r + 8) << 4 | (vg_b + 8);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bytes[p++] = QOI_OP_RGB;
|
||||||
|
bytes[p++] = px.rgba.r;
|
||||||
|
bytes[p++] = px.rgba.g;
|
||||||
|
bytes[p++] = px.rgba.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bytes[p++] = QOI_OP_RGBA;
|
||||||
|
bytes[p++] = px.rgba.r;
|
||||||
|
bytes[p++] = px.rgba.g;
|
||||||
|
bytes[p++] = px.rgba.b;
|
||||||
|
bytes[p++] = px.rgba.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
px_prev = px;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < (int)sizeof(qoi_padding); i++) {
|
||||||
|
bytes[p++] = qoi_padding[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_len = p;
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
|
||||||
|
const unsigned char *bytes;
|
||||||
|
unsigned int header_magic;
|
||||||
|
unsigned char *pixels;
|
||||||
|
qoi_rgba_t index[64];
|
||||||
|
qoi_rgba_t px;
|
||||||
|
int px_len, chunks_len, px_pos;
|
||||||
|
int p = 0, run = 0;
|
||||||
|
|
||||||
|
if (
|
||||||
|
data == NULL || desc == NULL ||
|
||||||
|
(channels != 0 && channels != 3 && channels != 4) ||
|
||||||
|
size < QOI_HEADER_SIZE + (int)sizeof(qoi_padding)
|
||||||
|
) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = (const unsigned char *)data;
|
||||||
|
|
||||||
|
header_magic = qoi_read_32(bytes, &p);
|
||||||
|
desc->width = qoi_read_32(bytes, &p);
|
||||||
|
desc->height = qoi_read_32(bytes, &p);
|
||||||
|
desc->channels = bytes[p++];
|
||||||
|
desc->colorspace = bytes[p++];
|
||||||
|
|
||||||
|
if (
|
||||||
|
desc->width == 0 || desc->height == 0 ||
|
||||||
|
desc->channels < 3 || desc->channels > 4 ||
|
||||||
|
desc->colorspace > 1 ||
|
||||||
|
header_magic != QOI_MAGIC ||
|
||||||
|
desc->height >= QOI_PIXELS_MAX / desc->width
|
||||||
|
) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channels == 0) {
|
||||||
|
channels = desc->channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
px_len = desc->width * desc->height * channels;
|
||||||
|
pixels = (unsigned char *) QOI_MALLOC(px_len);
|
||||||
|
if (!pixels) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QOI_ZEROARR(index);
|
||||||
|
px.rgba.r = 0;
|
||||||
|
px.rgba.g = 0;
|
||||||
|
px.rgba.b = 0;
|
||||||
|
px.rgba.a = 255;
|
||||||
|
|
||||||
|
chunks_len = size - (int)sizeof(qoi_padding);
|
||||||
|
for (px_pos = 0; px_pos < px_len; px_pos += channels) {
|
||||||
|
if (run > 0) {
|
||||||
|
run--;
|
||||||
|
}
|
||||||
|
else if (p < chunks_len) {
|
||||||
|
int b1 = bytes[p++];
|
||||||
|
|
||||||
|
if (b1 == QOI_OP_RGB) {
|
||||||
|
px.rgba.r = bytes[p++];
|
||||||
|
px.rgba.g = bytes[p++];
|
||||||
|
px.rgba.b = bytes[p++];
|
||||||
|
}
|
||||||
|
else if (b1 == QOI_OP_RGBA) {
|
||||||
|
px.rgba.r = bytes[p++];
|
||||||
|
px.rgba.g = bytes[p++];
|
||||||
|
px.rgba.b = bytes[p++];
|
||||||
|
px.rgba.a = bytes[p++];
|
||||||
|
}
|
||||||
|
else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) {
|
||||||
|
px = index[b1];
|
||||||
|
}
|
||||||
|
else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) {
|
||||||
|
px.rgba.r += ((b1 >> 4) & 0x03) - 2;
|
||||||
|
px.rgba.g += ((b1 >> 2) & 0x03) - 2;
|
||||||
|
px.rgba.b += ( b1 & 0x03) - 2;
|
||||||
|
}
|
||||||
|
else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) {
|
||||||
|
int b2 = bytes[p++];
|
||||||
|
int vg = (b1 & 0x3f) - 32;
|
||||||
|
px.rgba.r += vg - 8 + ((b2 >> 4) & 0x0f);
|
||||||
|
px.rgba.g += vg;
|
||||||
|
px.rgba.b += vg - 8 + (b2 & 0x0f);
|
||||||
|
}
|
||||||
|
else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) {
|
||||||
|
run = (b1 & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
index[QOI_COLOR_HASH(px) % 64] = px;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channels == 4) {
|
||||||
|
*(qoi_rgba_t*)(pixels + px_pos) = px;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pixels[px_pos + 0] = px.rgba.r;
|
||||||
|
pixels[px_pos + 1] = px.rgba.g;
|
||||||
|
pixels[px_pos + 2] = px.rgba.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef QOI_NO_STDIO
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int qoi_write(const char *filename, const void *data, const qoi_desc *desc) {
|
||||||
|
FILE *f = fopen(filename, "wb");
|
||||||
|
int size;
|
||||||
|
void *encoded;
|
||||||
|
|
||||||
|
if (!f) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
encoded = qoi_encode(data, desc, &size);
|
||||||
|
if (!encoded) {
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(encoded, 1, size, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
QOI_FREE(encoded);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *qoi_read(const char *filename, qoi_desc *desc, int channels) {
|
||||||
|
FILE *f = fopen(filename, "rb");
|
||||||
|
int size, bytes_read;
|
||||||
|
void *pixels, *data;
|
||||||
|
|
||||||
|
if (!f) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size = ftell(f);
|
||||||
|
if (size <= 0) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
data = QOI_MALLOC(size);
|
||||||
|
if (!data) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_read = fread(data, 1, size, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
pixels = qoi_decode(data, bytes_read, desc, channels);
|
||||||
|
QOI_FREE(data);
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* QOI_NO_STDIO */
|
||||||
|
#endif /* QOI_IMPLEMENTATION */
|
16
rres/go.mod
16
rres/go.mod
|
@ -1,17 +1,5 @@
|
||||||
module github.com/gen2brain/raylib-go/rres
|
module github.com/gen2brain/raylib-go/rres
|
||||||
|
|
||||||
go 1.16
|
go 1.19
|
||||||
|
|
||||||
replace github.com/gen2brain/raylib-go/raylib => ../raylib
|
require github.com/gen2brain/raylib-go/raylib v0.0.0-20230511170620-d84e4cc82f8d
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/dsnet/compress v0.0.1
|
|
||||||
github.com/frankban/quicktest v1.13.0 // indirect
|
|
||||||
github.com/gen2brain/raylib-go/raylib v0.0.0-20230307115054-60f06875ad1a
|
|
||||||
github.com/golang/snappy v0.0.4
|
|
||||||
github.com/klauspost/compress v1.16.0
|
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible
|
|
||||||
github.com/rootlch/encrypt v0.0.0-20120717064446-58e7f47a860b
|
|
||||||
github.com/ulikunitz/xz v0.5.11
|
|
||||||
golang.org/x/crypto v0.7.0
|
|
||||||
)
|
|
||||||
|
|
65
rres/go.sum
65
rres/go.sum
|
@ -1,63 +1,2 @@
|
||||||
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
|
github.com/gen2brain/raylib-go/raylib v0.0.0-20230511170620-d84e4cc82f8d h1:M1gq2devl4lx6K0Gky7CvbYrxMMP2uC903C9bO+GO28=
|
||||||
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
|
github.com/gen2brain/raylib-go/raylib v0.0.0-20230511170620-d84e4cc82f8d/go.mod h1:AwtGA3aTtYdezNxEVbfchaLw/z+CuRDh2Mlxy0FbBro=
|
||||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
|
||||||
github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk=
|
|
||||||
github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU=
|
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
|
||||||
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
|
||||||
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
|
||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
|
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
|
||||||
github.com/rootlch/encrypt v0.0.0-20120717064446-58e7f47a860b h1:06aiugVMPXHO5St9bxSpm2N2uowHODq2sPozLO+gclo=
|
|
||||||
github.com/rootlch/encrypt v0.0.0-20120717064446-58e7f47a860b/go.mod h1:X9D5dzJkrZcrZB5tJCL06gaWACx7V8IvFIiONW2foko=
|
|
||||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
|
||||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
|
||||||
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
||||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
|
|
1588
rres/raylib.h
Normal file
1588
rres/raylib.h
Normal file
File diff suppressed because it is too large
Load diff
23
rres/rres-raylib.go
Normal file
23
rres/rres-raylib.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package rres
|
||||||
|
|
||||||
|
// #include <raylib.h>
|
||||||
|
// #define RRES_RAYLIB_IMPLEMENTATION
|
||||||
|
// #define RRES_SUPPORT_COMPRESSION_LZ4
|
||||||
|
// #define RRES_SUPPORT_ENCRYPTION_AES
|
||||||
|
// #define RRES_SUPPORT_ENCRYPTION_XCHACHA20
|
||||||
|
// #include <rres-raylib.h>
|
||||||
|
// #include <rres.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
rl "github.com/gen2brain/raylib-go/raylib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadImageFromResource(chunk ResourceChunk) rl.Image {
|
||||||
|
cchunk := *(*C.rresResourceChunk)(unsafe.Pointer(&chunk))
|
||||||
|
ret := C.LoadImageFromResource(cchunk)
|
||||||
|
v := *(*rl.Image)(unsafe.Pointer(&ret))
|
||||||
|
return v
|
||||||
|
}
|
1094
rres/rres-raylib.h
Normal file
1094
rres/rres-raylib.h
Normal file
File diff suppressed because it is too large
Load diff
957
rres/rres.go
957
rres/rres.go
File diff suppressed because it is too large
Load diff
1091
rres/rres.h
Normal file
1091
rres/rres.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue