file reading
This commit is contained in:
commit
023563f713
|
@ -0,0 +1,10 @@
|
|||
bin/
|
||||
out/
|
||||
dist/
|
||||
|
||||
|
||||
*.exe
|
||||
*.out
|
||||
*.bin
|
||||
|
||||
*test.png
|
|
@ -0,0 +1,139 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
Duration uint32
|
||||
PlaneCount uint32
|
||||
Planes []*Plane
|
||||
CoordinateCount uint32
|
||||
Coordinates [][2]uint32
|
||||
Unknown1 string
|
||||
Sound_effect string
|
||||
Unknown2 string
|
||||
Camp CampSection
|
||||
}
|
||||
type CampSection struct {
|
||||
Params [7]uint32
|
||||
Array []byte
|
||||
Extra string
|
||||
}
|
||||
|
||||
type Animation struct {
|
||||
Title string
|
||||
|
||||
// std::vector<uint32> frame_offsets
|
||||
FrameCount uint32
|
||||
Frames []*Frame
|
||||
}
|
||||
|
||||
func (a *Animation) Decode(rd *bufio.Reader, version int) error {
|
||||
if err := binary.Read(rd, end, &a.FrameCount); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Frames = make([]*Frame, int(a.FrameCount))
|
||||
for i := range a.Frames {
|
||||
cf := &Frame{}
|
||||
a.Frames[i] = cf
|
||||
if err := binary.Read(rd, end, &cf.Duration); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &cf.PlaneCount); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cf.Planes = make([]*Plane, int(cf.PlaneCount))
|
||||
for i := range cf.Planes {
|
||||
cp := &Plane{}
|
||||
cf.Planes[i] = cp
|
||||
if err := binary.Read(rd, end, &cp.PlaneX); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &cp.PlaneY); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(rd, end, &cp.Opacity); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cp.RenderFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(rd, end, &cp.FlagParam); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if version != 300 {
|
||||
if err := binary.Read(rd, end, &cf.CoordinateCount); err != nil {
|
||||
return err
|
||||
}
|
||||
cf.Coordinates = make([][2]uint32, cf.CoordinateCount)
|
||||
for i := range cf.Coordinates {
|
||||
if err := binary.Read(rd, end, cf.Coordinates[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
switch version {
|
||||
case 300, 301:
|
||||
if _, err := rd.Discard(144); err != nil {
|
||||
return err
|
||||
}
|
||||
case 302, 303:
|
||||
if _, err := rd.Discard(96); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if version >= 302 {
|
||||
// entry blocks
|
||||
if _, err := rd.Discard(28 * 6); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// unknown1
|
||||
if _, err := rd.Discard(44); err != nil {
|
||||
return err
|
||||
}
|
||||
//sound_effect
|
||||
if _, err := rd.Discard(18); err != nil {
|
||||
return err
|
||||
}
|
||||
// unknown2
|
||||
if _, err := rd.Discard(18); err != nil {
|
||||
return err
|
||||
}
|
||||
var cast uint32
|
||||
|
||||
if err := binary.Read(rd, end, &cast); err != nil {
|
||||
return err
|
||||
}
|
||||
if version > 303 && (cast > 1) {
|
||||
cf.Camp = CampSection{}
|
||||
if err := binary.Read(rd, end, &cf.Camp.Params); err != nil {
|
||||
return err
|
||||
}
|
||||
sz := int(cf.Camp.Params[1]) * int(cf.Camp.Params[2])
|
||||
cf.Camp.Array = make([]byte, sz)
|
||||
if _, err := io.ReadFull(rd, cf.Camp.Array); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Plane struct {
|
||||
Bitmap_id uint32
|
||||
PlaneX int32
|
||||
PlaneY int32
|
||||
Opacity uint32
|
||||
Blend BlendMode
|
||||
FlagParam uint32
|
||||
RenderFlag uint32
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package nori
|
||||
|
||||
type BlendMode uint32
|
||||
|
||||
var (
|
||||
BlendMode_None BlendMode = 0
|
||||
BlendMode_Alpha BlendMode = 1
|
||||
// Blend_ALPHA
|
||||
BlendMode_InvertMul BlendMode = 2
|
||||
// Color_Invert | Blend_MUL
|
||||
BlendMode_Unknown3 BlendMode = 3
|
||||
BlendMode_Add BlendMode = 4
|
||||
BlendMode_InvertMul5 BlendMode = 5
|
||||
// Color_Invert | Blend_MUL
|
||||
BlendMode_Mul BlendMode = 6
|
||||
BlendMode_Mul7 BlendMode = 7
|
||||
BlendMode_Add8 BlendMode = 8
|
||||
)
|
|
@ -0,0 +1,71 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Image struct {
|
||||
Bpp uint32
|
||||
Count uint32
|
||||
Delay uint32
|
||||
OffsetX int32
|
||||
OffsetY int32
|
||||
|
||||
Width uint32
|
||||
Height uint32
|
||||
|
||||
Size uint32
|
||||
Data []byte
|
||||
|
||||
Frame image.Image
|
||||
}
|
||||
|
||||
func (i *Image) Decode(rd *bufio.Reader) error {
|
||||
cf := image.NewRGBA64(image.Rect(0, 0, int(i.Width), int(i.Height)))
|
||||
i.Frame = cf
|
||||
switch i.Bpp {
|
||||
case 8:
|
||||
rd.Discard(int(i.Size))
|
||||
return fmt.Errorf("bpp = 8, but no palette")
|
||||
case 16:
|
||||
var bgr uint16
|
||||
for idx := 0; idx < int(i.Size/2); idx++ {
|
||||
if err := binary.Read(rd, end, &bgr); err != nil {
|
||||
return err
|
||||
}
|
||||
red := uint8(((0x7c00 & bgr) >> 10) * 255 / 31)
|
||||
green := uint8(((0x3e0 & bgr) >> 5) * 255 / 31)
|
||||
blue := uint8((0x1f & bgr) * 255 / 31)
|
||||
if red != 0 && blue != 0 && green != 0 {
|
||||
}
|
||||
col := &color.RGBA{
|
||||
red, green, blue,
|
||||
0xff,
|
||||
}
|
||||
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
|
||||
}
|
||||
return nil
|
||||
case 24:
|
||||
i.Data = make([]byte, i.Size)
|
||||
for idx := 0; idx < int(i.Size/3); idx++ {
|
||||
rgb := [3]byte{}
|
||||
_, err := io.ReadFull(rd, rgb[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
col := &color.RGBA{
|
||||
rgb[0], rgb[1], rgb[2],
|
||||
0xff,
|
||||
}
|
||||
cf.Set(idx%int(i.Width), idx/int(i.Width), col)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported bpp, %d", i.Bpp)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package nori
|
||||
|
||||
type PaletteSection struct {
|
||||
Version uint32
|
||||
Param01 uint32
|
||||
Param02 uint32
|
||||
Param03 uint32
|
||||
Param04 uint32
|
||||
Divided bool
|
||||
DataLength uint32
|
||||
// Graphics::Palette color_data
|
||||
}
|
||||
|
||||
type GawiSection struct {
|
||||
Version uint32
|
||||
Bpp uint32
|
||||
IsCompressed bool
|
||||
Params [4]uint32
|
||||
BmpCount uint32
|
||||
Size uint32
|
||||
|
||||
HasPalette bool
|
||||
Palette *PaletteSection
|
||||
// std::vector<uint32> bmp_offsets
|
||||
Images []*Image
|
||||
}
|
||||
|
||||
type Nori struct {
|
||||
Version uint32
|
||||
Params [5]uint32
|
||||
AnimationCount uint32
|
||||
SizeNoGawi uint32
|
||||
TotalSize uint32
|
||||
|
||||
Gawi *GawiSection
|
||||
Animations []*Animation
|
||||
AnimationByKey map[string]*Animation
|
||||
|
||||
lastSignature [4]byte
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseFile1(t *testing.T) {
|
||||
rd, err := os.OpenFile("./nori_test/test1.nri", os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
t.Fatalf("open file: %s", err)
|
||||
}
|
||||
nori, err := NewReader(rd).Decode()
|
||||
if err != nil {
|
||||
t.Fatalf("decode: %s", err)
|
||||
}
|
||||
t.Logf("\n nori: %+v\n gawi: %+v", nori, nori.Gawi)
|
||||
}
|
||||
|
||||
func TestParseFile2(t *testing.T) {
|
||||
rd, err := os.OpenFile("./nori_test/test2.nri", os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
t.Fatalf("open file: %s", err)
|
||||
}
|
||||
nori, err := NewReader(rd).Decode()
|
||||
if err != nil {
|
||||
t.Fatalf("decode: %s", err)
|
||||
}
|
||||
t.Logf("\n nori: %+v\n gawi: %+v", nori, nori.Gawi)
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,165 @@
|
|||
package nori
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
var end = binary.LittleEndian
|
||||
|
||||
type Reader struct {
|
||||
nori *Nori
|
||||
|
||||
r *bufio.Reader
|
||||
}
|
||||
|
||||
func NewReader(rd io.Reader) *Reader {
|
||||
o := &Reader{
|
||||
nori: &Nori{},
|
||||
r: bufio.NewReader(rd),
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (n *Reader) Decode() (*Nori, error) {
|
||||
if _, err := io.ReadFull(n, n.nori.lastSignature[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sig, target := string(n.nori.lastSignature[:]), "NORI"; sig != target {
|
||||
return nil, fmt.Errorf("expected header %s, got %s", target, sig)
|
||||
}
|
||||
if err := binary.Read(n, end, &n.nori.Version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := binary.Read(n, end, n.nori.Params[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := binary.Read(n, end, &n.nori.AnimationCount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := binary.Read(n, end, &n.nori.SizeNoGawi); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := binary.Read(n, end, &n.nori.TotalSize); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := n.decodeGawi(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return n.nori, nil
|
||||
}
|
||||
|
||||
func (n *Reader) decodeGawi() error {
|
||||
g := &GawiSection{}
|
||||
n.nori.Gawi = g
|
||||
if _, err := io.ReadFull(n, n.nori.lastSignature[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if sig, target := string(n.nori.lastSignature[:]), "GAWI"; sig != target {
|
||||
return fmt.Errorf("bad sig: want %s, got %s", target, sig)
|
||||
}
|
||||
if err := binary.Read(n, end, &g.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if g.Version != 300 {
|
||||
return fmt.Errorf("bad ver: want 300, got %d", g.Version)
|
||||
}
|
||||
if err := binary.Read(n, end, &g.Bpp); err != nil {
|
||||
return err
|
||||
}
|
||||
good := false
|
||||
for _, v := range [3]uint32{8, 16, 24} {
|
||||
if g.Bpp == v {
|
||||
good = true
|
||||
}
|
||||
}
|
||||
if !good {
|
||||
return fmt.Errorf("bad bpp: %d", g.Bpp)
|
||||
}
|
||||
var container uint32
|
||||
if err := binary.Read(n, end, &container); err != nil {
|
||||
return err
|
||||
}
|
||||
g.IsCompressed = (container == 1)
|
||||
if err := binary.Read(n, end, &container); err != nil {
|
||||
return err
|
||||
}
|
||||
g.HasPalette = (container > 0)
|
||||
|
||||
if err := binary.Read(n, end, g.Params[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(n, end, &g.BmpCount); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Read(n, end, &g.Size); err != nil {
|
||||
return err
|
||||
}
|
||||
if g.HasPalette {
|
||||
n.decodePalette()
|
||||
}
|
||||
if _, err := n.r.Discard(4 * int(g.BmpCount)); err != nil {
|
||||
return err
|
||||
}
|
||||
g.Images = make([]*Image, int(g.BmpCount))
|
||||
for i := range g.Images {
|
||||
g.Images[i] = &Image{Bpp: g.Bpp}
|
||||
if err := n.decodeImage(g.Images[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := n.r.Discard(4 * int(n.nori.AnimationCount)); err != nil {
|
||||
return err
|
||||
}
|
||||
n.nori.Animations = make([]*Animation, n.nori.AnimationCount)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Reader) decodePalette() error {
|
||||
if sig, target := string(n.nori.lastSignature[:]), "PAL_"; sig != target {
|
||||
return fmt.Errorf("bad sig: want %s, got %s", target, sig)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (n *Reader) decodeImage(img *Image) error {
|
||||
if err := binary.Read(n, end, &img.Count); err != nil {
|
||||
return err
|
||||
}
|
||||
if img.Count != 1 {
|
||||
return fmt.Errorf("img count should be 1")
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.Size); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.Width); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.Height); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.Delay); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.OffsetX); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(n, end, &img.OffsetY); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := img.Decode(n.r); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Reader) Read(b []byte) (int, error) {
|
||||
return n.r.Read(b)
|
||||
}
|
Loading…
Reference in New Issue