Skip to content

Commit

Permalink
Support AmlResImg
Browse files Browse the repository at this point in the history
  • Loading branch information
hzyitc committed Jun 29, 2022
1 parent 448b888 commit eaeed9e
Show file tree
Hide file tree
Showing 6 changed files with 533 additions and 0 deletions.
119 changes: 119 additions & 0 deletions AmlResImg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package main

import (
"bufio"
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"

"github.com/hzyitc/AmlImg/AmlResImg"
)

func res_unpack(filePath, extractPath string) error {
img, err := AmlResImg.NewReader(filePath, true)
if err != nil {
return errors.New("NewReader error: " + err.Error())
}
defer img.Close()

listfile, err := os.Create(extractPath + "/list.txt")
if err != nil {
return errors.New("Create error: " + err.Error())
}
defer listfile.Close()

for i := 0; i < int(img.Header.ItemCount); i++ {
item := img.Items[i]

filename := fmt.Sprintf("%d.%s", item.Index, item.Name)
if item.Type == 0x090000 {
filename += ".bmp"
}

println("Extracting ", extractPath+"/"+filename)

fmt.Fprintf(listfile, "%08X:%s:%s\n", item.Type, item.Name, filename)

file, err := os.Create(extractPath + "/" + filename)
if err != nil {
return errors.New("Create error:" + err.Error())
}

err = img.Seek(uint32(i), 0)
if err != nil {
file.Close()
return errors.New("Seek error:" + err.Error())
}

_, err = io.Copy(file, img)
if err != nil {
file.Close()
return errors.New("Copy error:" + err.Error())
}

file.Close()
}

return nil
}

func res_pack(filePath, dirPath string) error {
img, err := AmlResImg.NewWriter()
if err != nil {
return errors.New("NewWriter error: " + err.Error())
}

listfile, err := os.Open(dirPath + "/list.txt")
if err != nil {
return errors.New("Open error: " + err.Error())
}
defer listfile.Close()

scanner := bufio.NewScanner(listfile)
scanner.Split(bufio.ScanLines)

for scanner.Scan() {
txt := scanner.Text()
if txt == "" {
continue
} else if strings.HasPrefix(txt, "#") {
continue
}

c := strings.SplitN(txt, ":", 3)
Name := c[1]
filename := c[2]

Type, err := strconv.ParseInt(c[0], 16, 24)
if err != nil {
return errors.New("ParseInt error: " + err.Error())
}

img.Add(uint32(Type), Name, func(w io.Writer) error {
println("Packing ", filename)

file, err := os.Open(dirPath + "/" + filename)
if err != nil {
return errors.New("Open error: " + err.Error())
}

_, err = io.Copy(w, file)
return err
})
}

err = scanner.Err()
if err != nil {
return errors.New("scanner error: " + err.Error())
}

err = img.Write(filePath, 2)
if err != nil {
return errors.New("Write error: " + err.Error())
}

return nil
}
30 changes: 30 additions & 0 deletions AmlResImg/header.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package AmlResImg

import (
"encoding/binary"
"io"
)

const (
Header_Magic = uint64(0x215345525F4C4D41) // "AML_RES!"
)

type Header struct {
CRC uint32
Version uint32
Magic uint64
Size uint32
ItemCount uint32
AlignSize uint32
Reserved [36]byte
}

func Header_Unpack(reader io.Reader) (*Header, error) {
header := Header{}
err := binary.Read(reader, binary.LittleEndian, &header)
return &header, err
}

func (header *Header) Pack(writer io.Writer) error {
return binary.Write(writer, binary.LittleEndian, header)
}
102 changes: 102 additions & 0 deletions AmlResImg/item.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package AmlResImg

import (
"bytes"
"encoding/binary"
"fmt"
"io"
)

const (
Item_Magic = uint32(0x27051956)
)

type Item_v2 struct {
Magic uint32
Header_CRC uint32
Size uint32
DataOffset uint32
Entry uint32
NextItemOffset uint32
Data_CRC uint32
Index uint8
Type1 uint8
Type2 uint8
Type3 uint8
Name [32]byte
}

type Item struct {
Magic uint32
Header_CRC uint32
Size uint32
DataOffset uint32
Entry uint32
NextItemOffset uint32
Data_CRC uint32
Index uint8
Type uint32
Name string
}

func Item_Unpack(reader io.Reader, version uint32) (*Item, error) {
if version == 2 {
d := Item_v2{}

buf := make([]byte, binary.Size(&d))
_, err := io.ReadFull(reader, buf)
if err != nil {
return nil, err
}

err = binary.Read(bytes.NewReader(buf), binary.LittleEndian, &d)
if err != nil {
return nil, err
}

// crc := uint32(0xffffffff)
// crc = AmlImg.AmlCRC(crc, buf[:4])
// crc = AmlImg.AmlCRC(crc, buf[8:])
// if d.Header_CRC != crc {
// return nil, fmt.Errorf("incorrect crc: should %08X but is %08X", d.Header_CRC, crc)
// }

return &Item{
d.Magic,
d.Header_CRC,
d.Size,
d.DataOffset,
d.Entry,
d.NextItemOffset,
d.Data_CRC,
d.Index,
uint32(d.Type1)<<16 | uint32(d.Type2)<<8 | uint32(d.Type3)<<0,
string(bytes.TrimRight(d.Name[:], "\x00")),
}, nil
} else {
return nil, fmt.Errorf("unsupport version: %d", version)
}
}

func (item *Item) Pack(writer io.Writer, version uint32) error {
if version == 2 {
d := Item_v2{
item.Magic,
item.Header_CRC,
item.Size,
item.DataOffset,
item.Entry,
item.NextItemOffset,
item.Data_CRC,
item.Index,
uint8((item.Type >> 16) & 0xFF),
uint8((item.Type >> 8) & 0xFF),
uint8((item.Type >> 0) & 0xFF),
[32]byte{},
}
copy(d.Name[:], []byte(item.Name))
return binary.Write(writer, binary.LittleEndian, d)
} else {
return fmt.Errorf("unsupport version: %d", version)
}
}
112 changes: 112 additions & 0 deletions AmlResImg/reader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package AmlResImg

import (
"encoding/binary"
"errors"
"fmt"
"io"
"os"

"github.com/hzyitc/AmlImg/AmlCRC"
)

type ImageReader struct {
file *os.File

Header *Header
Items []*Item

remain uint64
}

func NewReader(path string, check bool) (*ImageReader, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}

header, err := Header_Unpack(file)
if err != nil {
return nil, err
}

if header.Magic != Header_Magic {
return nil, fmt.Errorf("incorrect magic: should %08X but is %08X", Header_Magic, header.Magic)
}

if check {
_, err = file.Seek(4, io.SeekStart)
if err != nil {
return nil, err
}

crc := uint32(0xffffffff)
var buf [4096]byte
for {
n, err := file.Read(buf[:])
crc = AmlCRC.AmlCRC(crc, buf[:n])
if errors.Is(err, io.EOF) {
break
} else if err != nil {
return nil, err
}
}

if header.CRC != crc {
return nil, fmt.Errorf("incorrect crc: should %08X but is %08X", header.CRC, crc)
}
}

next := int64(binary.Size(Header{}))
items := make([]*Item, header.ItemCount)
for i := 0; i < int(header.ItemCount); i++ {
_, err = file.Seek(next, io.SeekStart)
if err != nil {
return nil, err
}

items[i], err = Item_Unpack(file, header.Version)
if err != nil {
return nil, err
}

if items[i].Magic != Item_Magic {
return nil, fmt.Errorf("item[%d]: incorrect magic: should %08X but is %08X", i, Header_Magic, header.Magic)
}

next = int64(items[i].NextItemOffset)
}

return &ImageReader{
file,
header,
items,
0,
}, nil
}

func (r *ImageReader) Seek(id uint32, offset uint64) error {
item := r.Items[id]
_, err := r.file.Seek(int64(item.DataOffset)+int64(offset), io.SeekStart)
r.remain = uint64(item.Size) - offset
return err
}

func (r *ImageReader) Read(b []byte) (int, error) {
if r.remain == 0 {
return 0, io.EOF
}

size := cap(b)
if size > int(r.remain) {
size = int(r.remain)
}

n, err := r.file.Read(b[:size])
r.remain -= uint64(n)
return n, err
}

func (r *ImageReader) Close() {
r.file.Close()
}
Loading

0 comments on commit eaeed9e

Please sign in to comment.