Skip to content

Commit 33e16f9

Browse files
committed
Adding support for JPAK 2.0 Extended
* Added JPKDirectoryEntry Model * Added JPKFileEntry Model * Added JMS Model (WIP)
1 parent 46ea282 commit 33e16f9

3 files changed

Lines changed: 245 additions & 0 deletions

File tree

js/jpak.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ JPAK.jpakloader.prototype.Load = function() {
217217
if (this.status === 200) {
218218
var data = this.response;
219219
var MagicNumber = u8as(new Uint8Array(data.slice(0,5)));
220+
var MagicNumber2 = u8as(new Uint8Array(data.slice(0,4)));
220221
if(MagicNumber === "JPAK1") {
221222
JPAK.log("JPAK::jpakloader - Loaded file "+_this.jpakfile+" successfully. JPAK1 Format");
222223
var filetableoffset = new DataView(data.slice(data.byteLength-4,data.byteLength)).getUint32(0, true);
@@ -227,6 +228,10 @@ JPAK.jpakloader.prototype.Load = function() {
227228
_this.dataloaded = true;
228229
if(_this.onload !== undefined)
229230
_this.onload();
231+
} else if(MagicNumber === "JMS1") {
232+
JPAK.log("JPAK::jpakloader - Loaded JPAK Metadata File "+_this.jpakfile+" successfully.");
233+
} else if(MagicNumber2 === "JDS1") {
234+
JPAK.log("JPAK::jpakloader - Loaded JPAK Storage File "+_this.jpakfile+" successfully.");
230235
}else{
231236
JPAK.log("JPAK::jpakloader - Error loading file "+_this.jpakfile+" (8000): Wrong File Magic. Expected JPAK1 got "+MagicNumber);
232237
if(_this.onerror !== undefined)

tools/extpacker.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env python
2+
3+
print '''
4+
_ ____ _ _ __ _____ _ ____ _
5+
| | _ \ / \ | |/ / | ____|_ _| |_ | _ \ __ _ ___| | _____ _ __
6+
_ | | |_) / _ \ | ' / | _| \ \/ / __| | |_) / _` |/ __| |/ / _ \ '__|
7+
| |_| | __/ ___ \| . \ | |___ > <| |_ | __/ (_| | (__| < __/ |
8+
\___/|_| /_/ \_\_|\_\ |_____/_/\_\\__| |_| \__,_|\___|_|\_\___|_|
9+
10+
Multiuse Javascript Package
11+
By: Lucas Teske
12+
https://github.com/racerxdl/jpak
13+
'''
14+
15+
16+
import struct, os, json, sys
17+
from jpaktool import *
18+
19+
if len(sys.argv) > 3:
20+
metadata = sys.argv[1]
21+
volume = sys.argv[2]
22+
user_args = sys.argv[3:]
23+
if os.path.isfile(metadata):
24+
print "Metadata %s has been found. Appending volume %s to JPAK" %(metadata, volume)
25+
else:
26+
print '''
27+
Usage: python packer.py metadata.jms volumeX.jds folder ...
28+
Ex: python packer.py myproject.jms volume0.jds /home/lucas/
29+
This will generate myproject.jms (or append a new volume) with contents of folder /home/lucas'''

tools/jpakmodels.py

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#!/usr/bin/env python
2+
3+
'''
4+
_ ____ _ _ __ ____ ___
5+
| | _ \ / \ | |/ / __ _|___ \ / _ \
6+
_ | | |_) / _ \ | ' / \ \ / / __) || | | |
7+
| |_| | __/ ___ \| . \ \ V / / __/ | |_| |
8+
\___/|_| /_/ \_\_|\_\ \_/ |_____(_)___/
9+
10+
Multiuse Javascript Package
11+
By: Lucas Teske
12+
https://github.com/racerxdl/jpak
13+
14+
'''
15+
16+
import json, struct
17+
18+
class JPKVolumeEntry:
19+
'''
20+
{
21+
"filename": "vol0.jds",
22+
"start": 0,
23+
"end": 1000
24+
}
25+
'''
26+
filename = ""
27+
start = 0
28+
end = 0
29+
30+
def __init__(self, filename="", start=0, end=0):
31+
self.filename = filename
32+
self.start = start
33+
self.end = end
34+
35+
def toObject(self):
36+
return {"filename":self.filename,"start":self.start,"end":self.end}
37+
38+
def fromObject(self, obj):
39+
self.filename = obj["filename"] if "filename" in obj else ""
40+
self.start = obj["start"] if "start" in obj else 0
41+
self.end = obj["end"] if "end" in obj else 0
42+
43+
class JPKFileEntry:
44+
'''
45+
fileentry = {
46+
"name" : FILENAME, // File Name
47+
"path" : FILEPATH, // File Path
48+
"offset" : FILEOFFSET, // Absolute offset in the jpak file
49+
"size" : FILESIZE // The file size
50+
"aeskey" : AESKEY // File key if != false
51+
"zlib" : FALSE/TRUE // If file is compressed
52+
"md5" : MD5SUM // Uncompresssed/unencrypted file MD5SUM
53+
}
54+
'''
55+
name = ""
56+
path = ""
57+
offset = 0
58+
size = 0
59+
aeskey = ""
60+
zlib = False
61+
md5 = ""
62+
63+
def __init__(self, name="", path="", offset=0, size=0, aeskey="", zlib=False, md5=""):
64+
self.name = name
65+
self.path = path
66+
self.offset = offset
67+
self.size = size
68+
self.aeskey = aeskey
69+
self.zlib = zlib
70+
self.md5 = md5
71+
72+
def toObject(self):
73+
return {"name":self.name, "path":self.path, "offset":self.offset, "size":self.size, "aeskey":self.aeskey, "zlib":self.zlib, "md5": self.md5}
74+
75+
def fromObject(self, obj):
76+
self.name = obj["name"] if "name" in obj else ""
77+
self.path = obj["path"] if "path" in obj else ""
78+
self.offset = obj["offset"] if "offset" in obj else ""
79+
self.size = obj["size"] if "size" in obj else ""
80+
self.aeskey = obj["aeskey"] if "aeskey" in obj else ""
81+
self.zlib = obj["zlib"] if "zlib" in obj else ""
82+
self.md5 = obj["md5"] if "md5" in obj else ""
83+
84+
class JPKDirectoryEntry:
85+
'''
86+
direntry = {
87+
"name" : DIRNAME, // Ndame of this folder
88+
"path" : DIRPATH, // Path for this folder
89+
"numfiles" : DIRNUMFILES, // Number of files in root of this folder
90+
"directories" : DIRSUBDIRECTORIES, // It's an array [] with directory objects like direntry
91+
"files" : DIRFILES // It's an array [] with file objects like fileentry
92+
"aeskey" : AESKEY // Folder key if != false
93+
}
94+
'''
95+
name = ""
96+
path = ""
97+
numfiles = 0
98+
directories = {}
99+
files = {}
100+
aeskey = ""
101+
102+
def __init__(self, name="", path="", numfiles=0, directories={}, files={}, aeskey=""):
103+
self.name = name
104+
self.path = path
105+
self.numfiles = numfiles
106+
self.directories = directories
107+
self.files = files
108+
self.aeskey = aeskey
109+
110+
def toObject(self):
111+
dirs = {}
112+
fls = {}
113+
for key, value in self.directories.iteritems():
114+
dirs[key] = value.toObject()
115+
116+
for key, value in self.files.iteritems():
117+
fls[key] = value.toObject()
118+
119+
return {"name":self.name, "path":self.path, "numfiles":len(self.files), "directories":dirs, "files":fls, "aeskey":self.aeskey}
120+
121+
def fromObject(self, obj):
122+
self.name = obj["name"] if "name" in obj else ""
123+
self.path = obj["path"] if "path" in obj else ""
124+
self.numfiles = obj["numfiles"] if "numfiles" in obj else ""
125+
self.aeskey = obj["aeskey"] if "aeskey" in obj else ""
126+
127+
if "directories" in obj:
128+
for key, value in obj["directories"].iteritems():
129+
d = JPKDirectoryEntry()
130+
d.fromObject(value)
131+
self.directories[key] = d
132+
133+
if "files" in obj:
134+
for key, value in obj["files"].iteritems():
135+
f = JPKFileEntry()
136+
f.fromObject(value)
137+
self.files[key] = f
138+
139+
def toJson(self):
140+
return json.dumps(self.toObject())
141+
142+
def fromJson(self, json):
143+
obj = json.loads(json)
144+
self.fromObject(obj)
145+
146+
def JMS:
147+
MAGIC = "JMS1"
148+
volumeTable = []
149+
fileTable = JPKDirectoryEntry()
150+
producerId = 0
151+
flags = 0
152+
userflags = 0
153+
154+
def __init__(self, volumeTable=[], fileTable={}, producerId=0, flags=0, userflags=0):
155+
self.volumeTable = volumeTable
156+
self.fileTable = fileTable
157+
self.producerId = producerId
158+
self.flags = flags
159+
self.userflags = userflags
160+
161+
def toObject(self):
162+
vt = []
163+
ft = {}
164+
for value in self.volumeTable:
165+
vt.append(value.toObject())
166+
167+
for key, value in self.fileTable:
168+
ft[key] = value.toObject()
169+
170+
return {"MAGIC":self.MAGIC, "volumeTable":vt, "fileTable":ft, "producerId": self.producerId, "flags":self.flags,"userflags":self.userflags}
171+
172+
def fromObject(self, obj):
173+
self.MAGIC = obj["MAGIC"] if "MAGIC" in obj else self.MAGIC
174+
self.producerId = obj["producerId"] if "producerId" in obj else 0
175+
self.flags = obj["flags"] if "flags" in obj else 0
176+
self.userflags = obj["userflags"] if "userflags" in obj else 0
177+
178+
self.fileTable = JPKDirectoryEntry()
179+
if "fileTable" in obj:
180+
self.fileTable.fromObject(obj["fileTable"])
181+
182+
self.volumeTable = []
183+
184+
if "volumeTable" in obj:
185+
for value in obj["volumeTable"]:
186+
v = JPKVolumeEntry()
187+
v.fromObject(value)
188+
self.volumeTable.append(v)
189+
190+
def fromBinary(self, data):
191+
self.MAGIC = data[:4]
192+
if not self.MAGIC == "JMS1":
193+
print "Invalid Magic for JMS file: %s" %self.MAGIC
194+
self.MAGIC = "JMS1"
195+
return
196+
197+
fileTableOffset = struct.unpack("<I", data[len(data)-4:len(data)])
198+
volumeTableSize = fileTableOffset - 0xC
199+
fileTableSize = len(data) - fileTableOffset - 12
200+
201+
fileTableData = json.loads(data[fileTableOffset:fileTableOffset+fileTableSize])
202+
volumeTableData = json.loads(data[0xC:volumeTableSize+0xC])
203+
204+
self.fileTable = JPKDirectoryEntry()
205+
self.fileTable.fromJson(fileTableData)
206+
207+
self.volumeTable = []
208+
for value in volumeTableData:
209+
v = JPKVolumeEntry()
210+
v.fromObject(value)
211+
self.volumeTable.append(v)

0 commit comments

Comments
 (0)