Skip to content

Commit eaeed9e

Browse files
committed
Support AmlResImg
1 parent 448b888 commit eaeed9e

File tree

6 files changed

+533
-0
lines changed

6 files changed

+533
-0
lines changed

AmlResImg.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"os"
9+
"strconv"
10+
"strings"
11+
12+
"github.com/hzyitc/AmlImg/AmlResImg"
13+
)
14+
15+
func res_unpack(filePath, extractPath string) error {
16+
img, err := AmlResImg.NewReader(filePath, true)
17+
if err != nil {
18+
return errors.New("NewReader error: " + err.Error())
19+
}
20+
defer img.Close()
21+
22+
listfile, err := os.Create(extractPath + "/list.txt")
23+
if err != nil {
24+
return errors.New("Create error: " + err.Error())
25+
}
26+
defer listfile.Close()
27+
28+
for i := 0; i < int(img.Header.ItemCount); i++ {
29+
item := img.Items[i]
30+
31+
filename := fmt.Sprintf("%d.%s", item.Index, item.Name)
32+
if item.Type == 0x090000 {
33+
filename += ".bmp"
34+
}
35+
36+
println("Extracting ", extractPath+"/"+filename)
37+
38+
fmt.Fprintf(listfile, "%08X:%s:%s\n", item.Type, item.Name, filename)
39+
40+
file, err := os.Create(extractPath + "/" + filename)
41+
if err != nil {
42+
return errors.New("Create error:" + err.Error())
43+
}
44+
45+
err = img.Seek(uint32(i), 0)
46+
if err != nil {
47+
file.Close()
48+
return errors.New("Seek error:" + err.Error())
49+
}
50+
51+
_, err = io.Copy(file, img)
52+
if err != nil {
53+
file.Close()
54+
return errors.New("Copy error:" + err.Error())
55+
}
56+
57+
file.Close()
58+
}
59+
60+
return nil
61+
}
62+
63+
func res_pack(filePath, dirPath string) error {
64+
img, err := AmlResImg.NewWriter()
65+
if err != nil {
66+
return errors.New("NewWriter error: " + err.Error())
67+
}
68+
69+
listfile, err := os.Open(dirPath + "/list.txt")
70+
if err != nil {
71+
return errors.New("Open error: " + err.Error())
72+
}
73+
defer listfile.Close()
74+
75+
scanner := bufio.NewScanner(listfile)
76+
scanner.Split(bufio.ScanLines)
77+
78+
for scanner.Scan() {
79+
txt := scanner.Text()
80+
if txt == "" {
81+
continue
82+
} else if strings.HasPrefix(txt, "#") {
83+
continue
84+
}
85+
86+
c := strings.SplitN(txt, ":", 3)
87+
Name := c[1]
88+
filename := c[2]
89+
90+
Type, err := strconv.ParseInt(c[0], 16, 24)
91+
if err != nil {
92+
return errors.New("ParseInt error: " + err.Error())
93+
}
94+
95+
img.Add(uint32(Type), Name, func(w io.Writer) error {
96+
println("Packing ", filename)
97+
98+
file, err := os.Open(dirPath + "/" + filename)
99+
if err != nil {
100+
return errors.New("Open error: " + err.Error())
101+
}
102+
103+
_, err = io.Copy(w, file)
104+
return err
105+
})
106+
}
107+
108+
err = scanner.Err()
109+
if err != nil {
110+
return errors.New("scanner error: " + err.Error())
111+
}
112+
113+
err = img.Write(filePath, 2)
114+
if err != nil {
115+
return errors.New("Write error: " + err.Error())
116+
}
117+
118+
return nil
119+
}

AmlResImg/header.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package AmlResImg
2+
3+
import (
4+
"encoding/binary"
5+
"io"
6+
)
7+
8+
const (
9+
Header_Magic = uint64(0x215345525F4C4D41) // "AML_RES!"
10+
)
11+
12+
type Header struct {
13+
CRC uint32
14+
Version uint32
15+
Magic uint64
16+
Size uint32
17+
ItemCount uint32
18+
AlignSize uint32
19+
Reserved [36]byte
20+
}
21+
22+
func Header_Unpack(reader io.Reader) (*Header, error) {
23+
header := Header{}
24+
err := binary.Read(reader, binary.LittleEndian, &header)
25+
return &header, err
26+
}
27+
28+
func (header *Header) Pack(writer io.Writer) error {
29+
return binary.Write(writer, binary.LittleEndian, header)
30+
}

AmlResImg/item.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package AmlResImg
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
"fmt"
7+
"io"
8+
)
9+
10+
const (
11+
Item_Magic = uint32(0x27051956)
12+
)
13+
14+
type Item_v2 struct {
15+
Magic uint32
16+
Header_CRC uint32
17+
Size uint32
18+
DataOffset uint32
19+
Entry uint32
20+
NextItemOffset uint32
21+
Data_CRC uint32
22+
Index uint8
23+
Type1 uint8
24+
Type2 uint8
25+
Type3 uint8
26+
Name [32]byte
27+
}
28+
29+
type Item struct {
30+
Magic uint32
31+
Header_CRC uint32
32+
Size uint32
33+
DataOffset uint32
34+
Entry uint32
35+
NextItemOffset uint32
36+
Data_CRC uint32
37+
Index uint8
38+
Type uint32
39+
Name string
40+
}
41+
42+
func Item_Unpack(reader io.Reader, version uint32) (*Item, error) {
43+
if version == 2 {
44+
d := Item_v2{}
45+
46+
buf := make([]byte, binary.Size(&d))
47+
_, err := io.ReadFull(reader, buf)
48+
if err != nil {
49+
return nil, err
50+
}
51+
52+
err = binary.Read(bytes.NewReader(buf), binary.LittleEndian, &d)
53+
if err != nil {
54+
return nil, err
55+
}
56+
57+
// crc := uint32(0xffffffff)
58+
// crc = AmlImg.AmlCRC(crc, buf[:4])
59+
// crc = AmlImg.AmlCRC(crc, buf[8:])
60+
// if d.Header_CRC != crc {
61+
// return nil, fmt.Errorf("incorrect crc: should %08X but is %08X", d.Header_CRC, crc)
62+
// }
63+
64+
return &Item{
65+
d.Magic,
66+
d.Header_CRC,
67+
d.Size,
68+
d.DataOffset,
69+
d.Entry,
70+
d.NextItemOffset,
71+
d.Data_CRC,
72+
d.Index,
73+
uint32(d.Type1)<<16 | uint32(d.Type2)<<8 | uint32(d.Type3)<<0,
74+
string(bytes.TrimRight(d.Name[:], "\x00")),
75+
}, nil
76+
} else {
77+
return nil, fmt.Errorf("unsupport version: %d", version)
78+
}
79+
}
80+
81+
func (item *Item) Pack(writer io.Writer, version uint32) error {
82+
if version == 2 {
83+
d := Item_v2{
84+
item.Magic,
85+
item.Header_CRC,
86+
item.Size,
87+
item.DataOffset,
88+
item.Entry,
89+
item.NextItemOffset,
90+
item.Data_CRC,
91+
item.Index,
92+
uint8((item.Type >> 16) & 0xFF),
93+
uint8((item.Type >> 8) & 0xFF),
94+
uint8((item.Type >> 0) & 0xFF),
95+
[32]byte{},
96+
}
97+
copy(d.Name[:], []byte(item.Name))
98+
return binary.Write(writer, binary.LittleEndian, d)
99+
} else {
100+
return fmt.Errorf("unsupport version: %d", version)
101+
}
102+
}

AmlResImg/reader.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package AmlResImg
2+
3+
import (
4+
"encoding/binary"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"os"
9+
10+
"github.com/hzyitc/AmlImg/AmlCRC"
11+
)
12+
13+
type ImageReader struct {
14+
file *os.File
15+
16+
Header *Header
17+
Items []*Item
18+
19+
remain uint64
20+
}
21+
22+
func NewReader(path string, check bool) (*ImageReader, error) {
23+
file, err := os.Open(path)
24+
if err != nil {
25+
return nil, err
26+
}
27+
28+
header, err := Header_Unpack(file)
29+
if err != nil {
30+
return nil, err
31+
}
32+
33+
if header.Magic != Header_Magic {
34+
return nil, fmt.Errorf("incorrect magic: should %08X but is %08X", Header_Magic, header.Magic)
35+
}
36+
37+
if check {
38+
_, err = file.Seek(4, io.SeekStart)
39+
if err != nil {
40+
return nil, err
41+
}
42+
43+
crc := uint32(0xffffffff)
44+
var buf [4096]byte
45+
for {
46+
n, err := file.Read(buf[:])
47+
crc = AmlCRC.AmlCRC(crc, buf[:n])
48+
if errors.Is(err, io.EOF) {
49+
break
50+
} else if err != nil {
51+
return nil, err
52+
}
53+
}
54+
55+
if header.CRC != crc {
56+
return nil, fmt.Errorf("incorrect crc: should %08X but is %08X", header.CRC, crc)
57+
}
58+
}
59+
60+
next := int64(binary.Size(Header{}))
61+
items := make([]*Item, header.ItemCount)
62+
for i := 0; i < int(header.ItemCount); i++ {
63+
_, err = file.Seek(next, io.SeekStart)
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
items[i], err = Item_Unpack(file, header.Version)
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
if items[i].Magic != Item_Magic {
74+
return nil, fmt.Errorf("item[%d]: incorrect magic: should %08X but is %08X", i, Header_Magic, header.Magic)
75+
}
76+
77+
next = int64(items[i].NextItemOffset)
78+
}
79+
80+
return &ImageReader{
81+
file,
82+
header,
83+
items,
84+
0,
85+
}, nil
86+
}
87+
88+
func (r *ImageReader) Seek(id uint32, offset uint64) error {
89+
item := r.Items[id]
90+
_, err := r.file.Seek(int64(item.DataOffset)+int64(offset), io.SeekStart)
91+
r.remain = uint64(item.Size) - offset
92+
return err
93+
}
94+
95+
func (r *ImageReader) Read(b []byte) (int, error) {
96+
if r.remain == 0 {
97+
return 0, io.EOF
98+
}
99+
100+
size := cap(b)
101+
if size > int(r.remain) {
102+
size = int(r.remain)
103+
}
104+
105+
n, err := r.file.Read(b[:size])
106+
r.remain -= uint64(n)
107+
return n, err
108+
}
109+
110+
func (r *ImageReader) Close() {
111+
r.file.Close()
112+
}

0 commit comments

Comments
 (0)