.dat file format of Fallout 2: Go parsing library

Application

Fallout 2

File extension

dat

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of .dat file format of Fallout 2 using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Go source code to parse .dat file format of Fallout 2

fallout2_dat.go

// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.

import (
	"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
	"io"
)


type Fallout2Dat_Compression int
const (
	Fallout2Dat_Compression__None Fallout2Dat_Compression = 0
	Fallout2Dat_Compression__Zlib Fallout2Dat_Compression = 1
)
var values_Fallout2Dat_Compression = map[Fallout2Dat_Compression]struct{}{0: {}, 1: {}}
func (v Fallout2Dat_Compression) isDefined() bool {
	_, ok := values_Fallout2Dat_Compression[v]
	return ok
}
type Fallout2Dat struct {
	_io *kaitai.Stream
	_root *Fallout2Dat
	_parent kaitai.Struct
	_f_footer bool
	footer *Fallout2Dat_Footer
	_f_index bool
	index *Fallout2Dat_Index
}
func NewFallout2Dat() *Fallout2Dat {
	return &Fallout2Dat{
	}
}

func (this Fallout2Dat) IO_() *kaitai.Stream {
	return this._io
}

func (this *Fallout2Dat) Read(io *kaitai.Stream, parent kaitai.Struct, root *Fallout2Dat) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	return err
}
func (this *Fallout2Dat) Footer() (v *Fallout2Dat_Footer, err error) {
	if (this._f_footer) {
		return this.footer, nil
	}
	this._f_footer = true
	_pos, err := this._io.Pos()
	if err != nil {
		return nil, err
	}
	tmp1, err := this._io.Size()
	if err != nil {
		return nil, err
	}
	_, err = this._io.Seek(int64(tmp1 - 8), io.SeekStart)
	if err != nil {
		return nil, err
	}
	tmp2 := NewFallout2Dat_Footer()
	err = tmp2.Read(this._io, this, this._root)
	if err != nil {
		return nil, err
	}
	this.footer = tmp2
	_, err = this._io.Seek(_pos, io.SeekStart)
	if err != nil {
		return nil, err
	}
	return this.footer, nil
}
func (this *Fallout2Dat) Index() (v *Fallout2Dat_Index, err error) {
	if (this._f_index) {
		return this.index, nil
	}
	this._f_index = true
	_pos, err := this._io.Pos()
	if err != nil {
		return nil, err
	}
	tmp3, err := this._io.Size()
	if err != nil {
		return nil, err
	}
	tmp4, err := this.Footer()
	if err != nil {
		return nil, err
	}
	_, err = this._io.Seek(int64((tmp3 - 8) - tmp4.IndexSize), io.SeekStart)
	if err != nil {
		return nil, err
	}
	tmp5 := NewFallout2Dat_Index()
	err = tmp5.Read(this._io, this, this._root)
	if err != nil {
		return nil, err
	}
	this.index = tmp5
	_, err = this._io.Seek(_pos, io.SeekStart)
	if err != nil {
		return nil, err
	}
	return this.index, nil
}
type Fallout2Dat_File struct {
	Name *Fallout2Dat_Pstr
	Flags Fallout2Dat_Compression
	SizeUnpacked uint32
	SizePacked uint32
	Offset uint32
	_io *kaitai.Stream
	_root *Fallout2Dat
	_parent *Fallout2Dat_Index
	_raw_contentsZlib []byte
	_f_contents bool
	contents []byte
	_f_contentsRaw bool
	contentsRaw []byte
	_f_contentsZlib bool
	contentsZlib []byte
}
func NewFallout2Dat_File() *Fallout2Dat_File {
	return &Fallout2Dat_File{
	}
}

func (this Fallout2Dat_File) IO_() *kaitai.Stream {
	return this._io
}

func (this *Fallout2Dat_File) Read(io *kaitai.Stream, parent *Fallout2Dat_Index, root *Fallout2Dat) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp6 := NewFallout2Dat_Pstr()
	err = tmp6.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Name = tmp6
	tmp7, err := this._io.ReadU1()
	if err != nil {
		return err
	}
	this.Flags = Fallout2Dat_Compression(tmp7)
	tmp8, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.SizeUnpacked = uint32(tmp8)
	tmp9, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.SizePacked = uint32(tmp9)
	tmp10, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Offset = uint32(tmp10)
	return err
}
func (this *Fallout2Dat_File) Contents() (v []byte, err error) {
	if (this._f_contents) {
		return this.contents, nil
	}
	this._f_contents = true
	if ( ((this.Flags == Fallout2Dat_Compression__Zlib) || (this.Flags == Fallout2Dat_Compression__None)) ) {
		var tmp11 []byte;
		if (this.Flags == Fallout2Dat_Compression__Zlib) {
			tmp12, err := this.ContentsZlib()
			if err != nil {
				return nil, err
			}
			tmp11 = tmp12
		} else {
			tmp13, err := this.ContentsRaw()
			if err != nil {
				return nil, err
			}
			tmp11 = tmp13
		}
		this.contents = []byte(tmp11)
	}
	return this.contents, nil
}
func (this *Fallout2Dat_File) ContentsRaw() (v []byte, err error) {
	if (this._f_contentsRaw) {
		return this.contentsRaw, nil
	}
	this._f_contentsRaw = true
	if (this.Flags == Fallout2Dat_Compression__None) {
		thisIo := this._root._io
		_pos, err := thisIo.Pos()
		if err != nil {
			return nil, err
		}
		_, err = thisIo.Seek(int64(this.Offset), io.SeekStart)
		if err != nil {
			return nil, err
		}
		tmp14, err := thisIo.ReadBytes(int(this.SizeUnpacked))
		if err != nil {
			return nil, err
		}
		tmp14 = tmp14
		this.contentsRaw = tmp14
		_, err = thisIo.Seek(_pos, io.SeekStart)
		if err != nil {
			return nil, err
		}
	}
	return this.contentsRaw, nil
}
func (this *Fallout2Dat_File) ContentsZlib() (v []byte, err error) {
	if (this._f_contentsZlib) {
		return this.contentsZlib, nil
	}
	this._f_contentsZlib = true
	if (this.Flags == Fallout2Dat_Compression__Zlib) {
		thisIo := this._root._io
		_pos, err := thisIo.Pos()
		if err != nil {
			return nil, err
		}
		_, err = thisIo.Seek(int64(this.Offset), io.SeekStart)
		if err != nil {
			return nil, err
		}
		tmp15, err := thisIo.ReadBytes(int(this.SizePacked))
		if err != nil {
			return nil, err
		}
		tmp15 = tmp15
		this._raw_contentsZlib = tmp15
		tmp16, err := kaitai.ProcessZlib(this._raw_contentsZlib)
		if err != nil {
			return nil, err
		}
		this.contentsZlib = tmp16
		_, err = thisIo.Seek(_pos, io.SeekStart)
		if err != nil {
			return nil, err
		}
	}
	return this.contentsZlib, nil
}
type Fallout2Dat_Footer struct {
	IndexSize uint32
	FileSize uint32
	_io *kaitai.Stream
	_root *Fallout2Dat
	_parent *Fallout2Dat
}
func NewFallout2Dat_Footer() *Fallout2Dat_Footer {
	return &Fallout2Dat_Footer{
	}
}

func (this Fallout2Dat_Footer) IO_() *kaitai.Stream {
	return this._io
}

func (this *Fallout2Dat_Footer) Read(io *kaitai.Stream, parent *Fallout2Dat, root *Fallout2Dat) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp17, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.IndexSize = uint32(tmp17)
	tmp18, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.FileSize = uint32(tmp18)
	return err
}
type Fallout2Dat_Index struct {
	FileCount uint32
	Files []*Fallout2Dat_File
	_io *kaitai.Stream
	_root *Fallout2Dat
	_parent *Fallout2Dat
}
func NewFallout2Dat_Index() *Fallout2Dat_Index {
	return &Fallout2Dat_Index{
	}
}

func (this Fallout2Dat_Index) IO_() *kaitai.Stream {
	return this._io
}

func (this *Fallout2Dat_Index) Read(io *kaitai.Stream, parent *Fallout2Dat, root *Fallout2Dat) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp19, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.FileCount = uint32(tmp19)
	for i := 0; i < int(this.FileCount); i++ {
		_ = i
		tmp20 := NewFallout2Dat_File()
		err = tmp20.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.Files = append(this.Files, tmp20)
	}
	return err
}
type Fallout2Dat_Pstr struct {
	Size uint32
	Str string
	_io *kaitai.Stream
	_root *Fallout2Dat
	_parent *Fallout2Dat_File
}
func NewFallout2Dat_Pstr() *Fallout2Dat_Pstr {
	return &Fallout2Dat_Pstr{
	}
}

func (this Fallout2Dat_Pstr) IO_() *kaitai.Stream {
	return this._io
}

func (this *Fallout2Dat_Pstr) Read(io *kaitai.Stream, parent *Fallout2Dat_File, root *Fallout2Dat) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp21, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Size = uint32(tmp21)
	tmp22, err := this._io.ReadBytes(int(this.Size))
	if err != nil {
		return err
	}
	tmp22 = tmp22
	this.Str = string(tmp22)
	return err
}