forked from hzyitc/AmlImg
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
533 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
} |
Oops, something went wrong.