mirror of
https://github.com/stevenhowes/PakGo.git
synced 2026-05-26 15:53:44 +01:00
110 lines
2.1 KiB
Go
110 lines
2.1 KiB
Go
package PakGo
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
type pakHeader struct {
|
|
Id [4]byte
|
|
Offset uint32
|
|
Size uint32
|
|
}
|
|
|
|
type pakFileEntry struct {
|
|
Name [56]byte
|
|
Offset uint32
|
|
Size uint32
|
|
}
|
|
|
|
type pakFileEntryNative struct {
|
|
Name string
|
|
Offset int64
|
|
Size int
|
|
}
|
|
|
|
type PakFile struct {
|
|
filetable []pakFileEntryNative
|
|
filehandle *os.File
|
|
}
|
|
|
|
func (pak PakFile) fileid(filename string, filetable []pakFileEntryNative) (int, error) {
|
|
for id, file := range filetable {
|
|
if filename == file.Name {
|
|
return id, nil
|
|
}
|
|
}
|
|
return -1, errors.New("the system cannot find the file specified")
|
|
}
|
|
|
|
func (pak PakFile) ReadFile(filename string) ([]byte, error) {
|
|
i, err := pak.fileid(filename, pak.filetable)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data := make([]byte, pak.filetable[i].Size)
|
|
pak.filehandle.Seek(pak.filetable[i].Offset, 0)
|
|
pak.filehandle.Read(data)
|
|
|
|
return data, nil
|
|
}
|
|
|
|
func (pak PakFile) PakClose() {
|
|
pak.filehandle.Close()
|
|
}
|
|
|
|
func PakLoad(filename string) (PakFile, error) {
|
|
var filetable []pakFileEntryNative
|
|
|
|
f, err := os.Open(filename)
|
|
if err != nil {
|
|
return PakFile{}, err
|
|
}
|
|
|
|
header := pakHeader{}
|
|
binary.Read(f, binary.LittleEndian, &header.Id)
|
|
binary.Read(f, binary.LittleEndian, &header.Offset)
|
|
binary.Read(f, binary.LittleEndian, &header.Size)
|
|
|
|
validheader := []byte{'P', 'A', 'C', 'K'}
|
|
valid := bytes.Compare(validheader, header.Id[:])
|
|
if valid != 0 {
|
|
return PakFile{}, errors.New("not a valid .PAK file")
|
|
}
|
|
|
|
size := reflect.TypeOf(pakFileEntry{}).Size()
|
|
filecount := int(header.Size / uint32(size))
|
|
|
|
f.Seek(int64(header.Offset), 0)
|
|
|
|
for i := 1; i <= filecount; i++ {
|
|
file := pakFileEntry{}
|
|
|
|
binary.Read(f, binary.LittleEndian, &file.Name)
|
|
binary.Read(f, binary.LittleEndian, &file.Offset)
|
|
binary.Read(f, binary.LittleEndian, &file.Size)
|
|
|
|
filename := string(file.Name[:])
|
|
filename = string(file.Name[:strings.Index(filename, "\x00")])
|
|
|
|
nativefile := pakFileEntryNative{
|
|
Name: filename,
|
|
Offset: int64(file.Offset),
|
|
Size: int(file.Size),
|
|
}
|
|
filetable = append(filetable, nativefile)
|
|
|
|
}
|
|
|
|
return PakFile{
|
|
filetable: filetable,
|
|
filehandle: f,
|
|
}, nil
|
|
}
|