mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-03 15:17:04 -05:00
db83814527
* d2mpq refactor * d2mpq refactor last standing lint error * d2mpq refactor: less linter noise * d2mpq refactor: more linter issues
78 lines
2.6 KiB
Go
78 lines
2.6 KiB
Go
package d2mpq
|
|
|
|
import (
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
// FileFlag represents flags for a file record in the MPQ archive
|
|
type FileFlag uint32
|
|
|
|
const (
|
|
// FileImplode - File is compressed using PKWARE Data compression library
|
|
FileImplode FileFlag = 0x00000100
|
|
// FileCompress - File is compressed using combination of compression methods
|
|
FileCompress FileFlag = 0x00000200
|
|
// FileEncrypted - The file is encrypted
|
|
FileEncrypted FileFlag = 0x00010000
|
|
// FileFixKey - The decryption key for the file is altered according to the position of the file in the archive
|
|
FileFixKey FileFlag = 0x00020000
|
|
// FilePatchFile - The file contains incremental patch for an existing file in base MPQ
|
|
FilePatchFile FileFlag = 0x00100000
|
|
// FileSingleUnit - Instead of being divided to 0x1000-bytes blocks, the file is stored as single unit
|
|
FileSingleUnit FileFlag = 0x01000000
|
|
// FileDeleteMarker - File is a deletion marker, indicating that the file no longer exists. This is used to allow patch
|
|
// archives to delete files present in lower-priority archives in the search chain. The file usually
|
|
// has length of 0 or 1 byte and its name is a hash
|
|
FileDeleteMarker FileFlag = 0x02000000
|
|
// FileSectorCrc - File has checksums for each sector. Ignored if file is not compressed or imploded.
|
|
FileSectorCrc FileFlag = 0x04000000
|
|
// FileExists - Set if file exists, reset when the file was deleted
|
|
FileExists FileFlag = 0x80000000
|
|
)
|
|
|
|
// Block represents an entry in the block table
|
|
type Block struct { // 16 bytes
|
|
FilePosition uint32
|
|
CompressedFileSize uint32
|
|
UncompressedFileSize uint32
|
|
Flags FileFlag
|
|
// Local Stuff...
|
|
FileName string
|
|
EncryptionSeed uint32
|
|
}
|
|
|
|
// HasFlag returns true if the specified flag is present
|
|
func (b *Block) HasFlag(flag FileFlag) bool {
|
|
return (b.Flags & flag) != 0
|
|
}
|
|
|
|
func (b *Block) calculateEncryptionSeed(fileName string) {
|
|
fileName = fileName[strings.LastIndex(fileName, `\`)+1:]
|
|
seed := hashString(fileName, 3)
|
|
b.EncryptionSeed = (seed + b.FilePosition) ^ b.UncompressedFileSize
|
|
}
|
|
|
|
//nolint:gomnd // number
|
|
func (mpq *MPQ) readBlockTable() error {
|
|
if _, err := mpq.file.Seek(int64(mpq.header.BlockTableOffset), io.SeekStart); err != nil {
|
|
return err
|
|
}
|
|
|
|
blockData, err := decryptTable(mpq.file, mpq.header.BlockTableEntries, "(block table)")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for n, i := uint32(0), uint32(0); i < mpq.header.BlockTableEntries; n, i = n+4, i+1 {
|
|
mpq.blocks = append(mpq.blocks, &Block{
|
|
FilePosition: blockData[n],
|
|
CompressedFileSize: blockData[n+1],
|
|
UncompressedFileSize: blockData[n+2],
|
|
Flags: FileFlag(blockData[n+3]),
|
|
})
|
|
}
|
|
|
|
return nil
|
|
}
|