mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-09-06 11:34:15 -04:00
* d2mpq refactor * d2mpq refactor last standing lint error * d2mpq refactor: less linter noise * d2mpq refactor: more linter issues
132 lines
3.1 KiB
Go
132 lines
3.1 KiB
Go
package d2mpq
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
var cryptoBuffer [0x500]uint32 //nolint:gochecknoglobals // will fix later..
|
|
var cryptoBufferReady bool //nolint:gochecknoglobals // will fix later..
|
|
|
|
func cryptoLookup(index uint32) uint32 {
|
|
if !cryptoBufferReady {
|
|
cryptoInitialize()
|
|
|
|
cryptoBufferReady = true
|
|
}
|
|
|
|
return cryptoBuffer[index]
|
|
}
|
|
|
|
//nolint:gomnd // Decryption magic
|
|
func cryptoInitialize() {
|
|
seed := uint32(0x00100001)
|
|
|
|
for index1 := 0; index1 < 0x100; index1++ {
|
|
index2 := index1
|
|
|
|
for i := 0; i < 5; i++ {
|
|
seed = (seed*125 + 3) % 0x2AAAAB
|
|
temp1 := (seed & 0xFFFF) << 0x10
|
|
seed = (seed*125 + 3) % 0x2AAAAB
|
|
temp2 := seed & 0xFFFF
|
|
cryptoBuffer[index2] = temp1 | temp2
|
|
index2 += 0x100
|
|
}
|
|
}
|
|
}
|
|
|
|
//nolint:gomnd // Decryption magic
|
|
func decrypt(data []uint32, seed uint32) {
|
|
seed2 := uint32(0xeeeeeeee)
|
|
|
|
for i := 0; i < len(data); i++ {
|
|
seed2 += cryptoLookup(0x400 + (seed & 0xff))
|
|
result := data[i]
|
|
result ^= seed + seed2
|
|
|
|
seed = ((^seed << 21) + 0x11111111) | (seed >> 11)
|
|
seed2 = result + seed2 + (seed2 << 5) + 3
|
|
data[i] = result
|
|
}
|
|
}
|
|
|
|
//nolint:gomnd // Decryption magic
|
|
func decryptBytes(data []byte, seed uint32) {
|
|
seed2 := uint32(0xEEEEEEEE)
|
|
for i := 0; i < len(data)-3; i += 4 {
|
|
seed2 += cryptoLookup(0x400 + (seed & 0xFF))
|
|
result := binary.LittleEndian.Uint32(data[i : i+4])
|
|
result ^= seed + seed2
|
|
seed = ((^seed << 21) + 0x11111111) | (seed >> 11)
|
|
seed2 = result + seed2 + (seed2 << 5) + 3
|
|
|
|
data[i+0] = uint8(result & 0xff)
|
|
data[i+1] = uint8((result >> 8) & 0xff)
|
|
data[i+2] = uint8((result >> 16) & 0xff)
|
|
data[i+3] = uint8((result >> 24) & 0xff)
|
|
}
|
|
}
|
|
|
|
//nolint:gomnd // Decryption magic
|
|
func decryptTable(r io.Reader, size uint32, name string) ([]uint32, error) {
|
|
seed := hashString(name, 3)
|
|
seed2 := uint32(0xEEEEEEEE)
|
|
size *= 4
|
|
|
|
table := make([]uint32, size)
|
|
buf := make([]byte, 4)
|
|
|
|
for i := uint32(0); i < size; i++ {
|
|
seed2 += cryptoBuffer[0x400+(seed&0xff)]
|
|
|
|
if _, err := r.Read(buf); err != nil {
|
|
return table, err
|
|
}
|
|
|
|
result := binary.LittleEndian.Uint32(buf)
|
|
result ^= seed + seed2
|
|
|
|
seed = ((^seed << 21) + 0x11111111) | (seed >> 11)
|
|
seed2 = result + seed2 + (seed2 << 5) + 3
|
|
table[i] = result
|
|
}
|
|
|
|
return table, nil
|
|
}
|
|
|
|
func hashFilename(key string) uint64 {
|
|
a, b := hashString(key, 1), hashString(key, 2)
|
|
return uint64(a)<<32 | uint64(b)
|
|
}
|
|
|
|
//nolint:gomnd // Decryption magic
|
|
func hashString(key string, hashType uint32) uint32 {
|
|
seed1 := uint32(0x7FED7FED)
|
|
seed2 := uint32(0xEEEEEEEE)
|
|
|
|
/* prepare seeds. */
|
|
for _, char := range strings.ToUpper(key) {
|
|
seed1 = cryptoLookup((hashType*0x100)+uint32(char)) ^ (seed1 + seed2)
|
|
seed2 = uint32(char) + seed1 + seed2 + (seed2 << 5) + 3
|
|
}
|
|
|
|
return seed1
|
|
}
|
|
|
|
//nolint:unused,deadcode,gomnd // will use this for creating mpq's
|
|
func encrypt(data []uint32, seed uint32) {
|
|
seed2 := uint32(0xeeeeeeee)
|
|
|
|
for i := 0; i < len(data); i++ {
|
|
seed2 += cryptoLookup(0x400 + (seed & 0xff))
|
|
result := data[i]
|
|
result ^= seed + seed2
|
|
|
|
seed = ((^seed << 21) + 0x11111111) | (seed >> 11)
|
|
seed2 = data[i] + seed2 + (seed2 << 5) + 3
|
|
data[i] = result
|
|
}
|
|
}
|