mirror of
https://github.com/stevenhowes/PakGo.git
synced 2026-05-26 15:53:44 +01:00
Initial commit of PakGo. TODO: HTTP filesysystem / os.file stuff
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user