commit 3617b0daa3c01d8c56910b2e967b12391cac0f18 Author: stevenhowes <38082088+stevenhowes@users.noreply.github.com> Date: Thu Jan 13 22:21:55 2022 +0000 Initial commit of PakGo. TODO: HTTP filesysystem / os.file stuff diff --git a/PakGo.go b/PakGo.go new file mode 100644 index 0000000..6649128 --- /dev/null +++ b/PakGo.go @@ -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 +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..6711e10 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Docs coming in next couple of days.. \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b4651eb --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/stevenhowes/PakGo + +go 1.17