-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlmd.go
113 lines (95 loc) · 2.18 KB
/
lmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package main
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
)
type gameID int
func (g gameID) String() string {
switch g {
case gameCC1:
return "cc1"
case gameRA1:
return "ra1"
case gameCC2:
return "cc2"
case gameRA2:
return "ra2"
default:
return ""
}
}
const (
gameCC1 gameID = 0
gameRA1 gameID = 1
gameCC2 gameID = 2
gameRA2 gameID = 5
lmdHeader = "XCC by Olaf van der Spek\x1a\x04\x17\x27\x10\x19\x80\x00"
)
const lmdFilename = "local mix database.dat"
func lmdWrite(game gameID, files []fileInfo) (fileInfo, error) {
var b bytes.Buffer
if _, err := b.WriteString(lmdFilename); err != nil {
return nil, err
}
size := uint32(52 + 1 + len(lmdFilename))
var filesToKeep []fileInfo
for _, f := range files {
if _, ok := filenameIsID(f.Name()); !ok {
filesToKeep = append(filesToKeep, f)
size += uint32(1 + len(f.Name()))
}
}
for _, v := range []uint32{size, 0, 0, uint32(game), 1 + uint32(len(files))} {
if _, err := writeUint32(&b, v); err != nil {
return nil, err
}
}
for _, f := range filesToKeep {
if _, err := fmt.Fprintf(&b, "%s\x00", f.Name()); err != nil {
return nil, err
}
}
if _, err := fmt.Fprintf(&b, "%s\x00", lmdFilename); err != nil {
return nil, err
}
return &bufferFileInfo{
name: lmdFilename,
buffer: b,
}, nil
}
func lmdRead(r io.ReadSeeker) (map[uint32]string, error) {
var hdr [32]byte
if _, err := r.Read(hdr[:]); err != nil {
return nil, err
} else if string(hdr[:]) != lmdHeader {
return nil, errors.New("not a local mix database")
} else if _, err := r.Seek(12, io.SeekCurrent); err != nil {
return nil, err
} else if gameid, err := readUint32(r); err != nil {
return nil, err
} else if _, err := r.Seek(4, io.SeekCurrent); err != nil {
return nil, err
} else {
mapper := map[uint32]string{}
fileID := getFileID(gameID(gameid))
scanner := bufio.NewScanner(r)
scanner.Split(scanZStrings)
for scanner.Scan() {
filename := scanner.Text()
mapper[fileID(filename)] = filename
}
if err := scanner.Err(); err != nil {
return nil, err
}
return mapper, nil
}
}
func getLmdFileID(game gameID) uint32 {
if game <= gameRA1 {
return 0x54C2D545
}
return 0x366E051F
}