hacktools 0.36.0__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
hacktools/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "0.36.0"
hacktools/arch.py ADDED
@@ -0,0 +1,137 @@
1
+ import os
2
+ from hacktools import common
3
+
4
+
5
+ class ARCHArchive:
6
+ def __init__(self):
7
+ self.filenum = 0
8
+ self.tableoff = 0
9
+ self.fatoff = 0
10
+ self.nameindexoff = 0
11
+ self.dataoff = 0
12
+ self.files = []
13
+
14
+
15
+ class ARCHFile:
16
+ def __init__(self):
17
+ self.name = ""
18
+ self.length = 0
19
+ self.declength = 0
20
+ self.offset = 0
21
+ self.nameoffset = 0
22
+ self.encoded = False
23
+
24
+
25
+ def read(f):
26
+ f.seek(4) # Magic: ARCH
27
+ archive = ARCHArchive()
28
+ archive.filenum = f.readUInt()
29
+ archive.tableoff = f.readUInt()
30
+ archive.fatoff = f.readUInt()
31
+ archive.nameindexoff = f.readUInt()
32
+ archive.dataoff = f.readUInt()
33
+ common.logDebug("Archive:", vars(archive))
34
+ for i in range(archive.filenum):
35
+ f.seek(archive.fatoff + i * 16)
36
+ subfile = ARCHFile()
37
+ subfile.length = f.readUInt()
38
+ subfile.declength = f.readUInt()
39
+ subfile.offset = f.readUInt()
40
+ subfile.nameoffset = f.readUShort()
41
+ subfile.encoded = f.readUShort() == 1
42
+ f.seek(archive.tableoff + subfile.nameoffset)
43
+ subfile.name = f.readNullString()
44
+ common.logDebug("File", i, vars(subfile))
45
+ archive.files.append(subfile)
46
+ return archive
47
+
48
+
49
+ def repack(fin, f, archive, infolder):
50
+ # Copy everything up to dataoff
51
+ fin.seek(0)
52
+ f.seek(0)
53
+ f.write(fin.read(archive.dataoff))
54
+ # Loop the files
55
+ dataoff = 0
56
+ for i in range(archive.filenum):
57
+ subfile = archive.files[i]
58
+ filepath = infolder + subfile.name
59
+ if not os.path.isfile(filepath):
60
+ # Just update the offset and copy the file
61
+ f.seek(archive.fatoff + i * 16)
62
+ f.seek(8, 1)
63
+ f.writeUInt(dataoff)
64
+ fin.seek(archive.dataoff + subfile.offset)
65
+ f.seek(archive.dataoff + dataoff)
66
+ f.write(fin.read(subfile.length))
67
+ else:
68
+ # Set the file as not encoded and copy it
69
+ size = os.path.getsize(filepath)
70
+ f.seek(archive.fatoff + i * 16)
71
+ f.writeUInt(size)
72
+ f.writeUInt(size)
73
+ f.writeUInt(dataoff)
74
+ f.seek(2, 1)
75
+ f.writeUShort(0)
76
+ f.seek(archive.dataoff + dataoff)
77
+ with common.Stream(filepath, "rb") as subf:
78
+ f.write(subf.read())
79
+ # Align with 0s
80
+ if f.tell() % 16 > 0:
81
+ f.writeZero(16 - (f.tell() % 16))
82
+ dataoff = f.tell() - archive.dataoff
83
+
84
+
85
+ def extract(f, archive, outfolder):
86
+ for subfile in archive.files:
87
+ with common.Stream(outfolder + subfile.name, "wb") as fout:
88
+ f.seek(archive.dataoff + subfile.offset)
89
+ if not subfile.encoded:
90
+ fout.write(f.read(subfile.length))
91
+ else:
92
+ # Based on Tinke's ARCH implementation
93
+ startpos = f.tell()
94
+ buffer1 = []
95
+ buffer2 = []
96
+ for i in range(0x100):
97
+ buffer1.append(0)
98
+ buffer2.append(0)
99
+ while f.tell() - startpos < subfile.length:
100
+ # InitBuffer
101
+ for i in range(0x100):
102
+ buffer2[i] = i
103
+ # FillBuffer
104
+ index = 0
105
+ while index != 0x100:
106
+ bufid = f.readByte()
107
+ numloops = bufid
108
+ if bufid > 0x7f:
109
+ numloops = 0
110
+ index += bufid - 0x7f
111
+ if index == 0x100:
112
+ break
113
+ if numloops < 0:
114
+ continue
115
+ for i in range(numloops + 1):
116
+ byte = f.readByte()
117
+ buffer2[index] = byte
118
+ if byte != index:
119
+ buffer1[index] = f.readByte()
120
+ index += 1
121
+ # Process
122
+ numloops = (f.readByte() << 8) + f.readByte()
123
+ nextsamples = []
124
+ while True:
125
+ if len(nextsamples) == 0:
126
+ if numloops == 0:
127
+ break
128
+ numloops -= 1
129
+ index = f.readByte()
130
+ else:
131
+ index = nextsamples.pop()
132
+ if buffer2[index] == index:
133
+ fout.writeByte(index)
134
+ else:
135
+ nextsamples.append(buffer1[index])
136
+ nextsamples.append(buffer2[index])
137
+ index = len(nextsamples)
Binary file
Binary file
Binary file
Binary file
Binary file