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