Skip to content

Commit

Permalink
Initial item.iff loading support.
Browse files Browse the repository at this point in the history
  • Loading branch information
jchv committed Jun 10, 2023
1 parent b1744df commit c5e37d8
Show file tree
Hide file tree
Showing 21 changed files with 670 additions and 27 deletions.
30 changes: 8 additions & 22 deletions pangya/iff/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,14 @@

package iff

import "github.com/pangbox/server/pangya"

type Header struct {
RecordCount uint16
BindingID uint16
Version uint32
type File[T any] struct {
Header
Records []T `struct:"size=Header.RecordCount"`
}

type Common struct {
Active uint32
ID uint32
Name string `struct:"[40]byte"`
Level byte
Icon string `struct:"[40]byte"`
Price uint32
DiscountPrice uint32
UsedPrice uint32
ShopFlag byte
MoneyFlag byte
TimeFlag byte
TimeByte byte
Point uint32
StartTime pangya.SystemTime
EndTime pangya.SystemTime
type Header struct {
/* 0x00 */ RecordCount uint16
/* 0x02 */ BindingID uint16
/* 0x04 */ Version Version
/* 0x08 */
}
23 changes: 21 additions & 2 deletions pangya/iff/course.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,31 @@

package iff

import "github.com/pangbox/server/pangya"

type Course struct {
Common Common
Active bool
_ [3]byte
ID uint32
Name string `struct:"[40]byte"`
Level byte
Icon string `struct:"[40]byte"`
_ [3]byte
Price uint32
DiscountPrice uint32
Condition uint32
ShopFlag byte
MoneyFlag byte
TimeFlag byte
TimeByte byte
Point uint32
Unknown [0x1C]byte
StartTime pangya.SystemTime
EndTime pangya.SystemTime
ShortName string `struct:"[40]byte"`
LocalizedName string `struct:"[40]byte"`
CourseFlag byte
PropertyFileName string `struct:"[40]byte"`
Unknown uint32
Unknown2 uint32
CourseSequence string `struct:"[40]byte"`
}
104 changes: 103 additions & 1 deletion pangya/iff/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ package iff
import (
"archive/zip"
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"

"github.com/go-restruct/restruct"
"github.com/pangbox/pangfiles/pak"
log "github.com/sirupsen/logrus"
)

type Archive struct {
ItemMap map[uint32]*Item
}

// Filenames to look for to find client IFF.
Expand All @@ -50,14 +54,112 @@ func LoadFromPak(fs pak.FS) (*Archive, error) {
}

func Load(data []byte) (*Archive, error) {
archive := &Archive{}
r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil {
return nil, err
}
for _, f := range r.File {
log.Debugf("Found IFF: %s", f.Name)
if f.Name == "Item.iff" {
r, err := f.Open()
if err != nil {
return nil, err
}
defer r.Close()
data, err := io.ReadAll(r)
if err != nil {
return nil, err
}
archive.loadItems(data)
}
}
return archive, nil
}

func (a *Archive) loadItems(data []byte) error {
file, err := LoadItems(data)
if err != nil {
return err
}
a.ItemMap = make(map[uint32]*Item)
for _, item := range file.Records {
a.ItemMap[item.ID] = &item
}
return nil
}

func LoadItems(data []byte) (*File[Item], error) {
recordCount := binary.LittleEndian.Uint16(data[:2])
recordLength := (len(data) - 0x8) / int(recordCount)
version := Version(binary.LittleEndian.Uint32(data[4:8]))

switch version {
case Version11:
switch recordLength {
case 0x78:
return loadItemVersion[ItemV11_78](data)
case 0x98:
return loadItemVersion[ItemV11_98](data)
case 0xB0:
return loadItemVersion[ItemV11_B0](data)
case 0xC0:
return loadItemVersion[ItemV11_C0](data)
case 0xC4:
return loadItemVersion[ItemV11_C4](data)
case 0xD8:
// JP4xx has the common times after the model name
// this is back to normal in JP5xx
var testItem ItemV11_D8_2
restruct.Unpack(data[8:], binary.LittleEndian, &testItem)
if testItem.StartTime.IsZero() || testItem.StartTime.IsValid() {
return loadItemVersion[ItemV11_D8_2](data)
} else {
return loadItemVersion[ItemV11_D8_1](data)
}
default:
return nil, fmt.Errorf("unknown item iff v%d record size %d (please report)", version, recordLength)
}
case Version13:
switch recordLength {
case 0xE0:
return loadItemVersion[ItemV13_E0](data)
case 0xF8:
return loadItemVersion[ItemV13_F8](data)
default:
return nil, fmt.Errorf("unknown item iff v%d record size %d (please report)", version, recordLength)
}
default:
return nil, errors.New("unknown item iff version")
}
}

func loadItemVersion[T itemGeneric](data []byte) (*File[Item], error) {
result := &File[Item]{}
f, err := LoadFile[T](data)
if err != nil {
return nil, err
}
result.Header = f.Header
for _, record := range f.Records {
result.Records = append(result.Records, record.Generic())
}
size, err := restruct.SizeOf(f)
if err != nil {
return nil, err
}
if len(data) > size {
return nil, fmt.Errorf("short read: read %d of %d bytes", size, len(data))
}
return result, nil
}

func LoadFile[T any](data []byte) (*File[T], error) {
file := &File[T]{}
if err := restruct.Unpack(data, binary.LittleEndian, file); err != nil {
return nil, err
}
return &Archive{}, nil
return file, nil
}

func findPangYaIFF(fs pak.FS) ([]byte, error) {
Expand Down
Loading

0 comments on commit c5e37d8

Please sign in to comment.