-
-
Save Vince0789/324ac3d8db5ddf7ebd03ea79ba365c6a to your computer and use it in GitHub Desktop.
An IPL decompiler for binary IPL data files for gta:sa.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Benjamin Williams | |
## <[email protected]> | |
## -- | |
## bipltool.py/pyc | |
import os | |
import sys | |
import struct | |
import math | |
#Base path to read from | |
basePath = "T:\\gtasa\\data\\maps\\exported\\"; | |
outputPath = basePath + "output\\"; | |
#File to read from | |
file = "vegasn_stream6.ipl"; | |
for file in [x for x in os.listdir(basePath) if x.endswith(".ipl")]: | |
print("[opening " + basePath + file + "...]"); | |
#Open up the file | |
f = open(basePath + file, "rb"); | |
#INST and CARS block output | |
instLines = []; | |
carLines = []; | |
try: | |
header = f.read(4); | |
if header != b"bnry": | |
print("\t[!] Target file is not a binary ipl file. (Failed file signature)\n"); | |
f.close(); | |
continue; | |
else: | |
print("\t[!] Target file is a binary ipl file. Reading header.."); | |
numberOfInsts = struct.unpack('i', f.read(4))[0]; | |
print("\t[head] INST block has " + str(numberOfInsts) + " items."); | |
#Skip unknown bytes (4 * 3) | |
f.seek(f.tell() + 4 * 3); | |
numberOfCars = struct.unpack('i', f.read(4))[0]; | |
print("\t[head] CARS block has " + str(numberOfCars) + " items."); | |
#Skip unknown bytes (4 * 1) | |
f.seek(f.tell() + 4); | |
offset = struct.unpack('i', f.read(4))[0]; | |
print(str(offset) + " is the offset for the INST block.\n"); | |
#Skip junk data (11 * 4) | |
f.seek(f.tell() + (11 * 4)); | |
print("\t[!] Read header values. Reading INST block:"); | |
#INST | |
for i in range(0, numberOfInsts): | |
posX = struct.unpack('f', f.read(4))[0]; | |
posY = struct.unpack('f', f.read(4))[0]; | |
posZ = struct.unpack('f', f.read(4))[0]; | |
rotX = struct.unpack('f', f.read(4))[0]; | |
rotY = struct.unpack('f', f.read(4))[0]; | |
rotZ = struct.unpack('f', f.read(4))[0]; | |
rotW = struct.unpack('f', f.read(4))[0]; | |
objID = struct.unpack('i', f.read(4))[0]; | |
unk = struct.unpack('i', f.read(4))[0]; | |
flags = struct.unpack('i', f.read(4))[0]; | |
#ID, ModelName, Interior, PosX, PosY, PosZ, RotX, RotY, RotZ, RotW, LOD | |
instLines.append("%d, dummy, %d, %.5f, %.5f, %.5f, %.5f, %.5f, %.5f, %.5f, %d" % (objID, unk, posX, posY, posZ, rotX, rotY, rotZ, rotW, flags)); | |
#print("\t\t[INST] Read and appended entry " + str(i + 1) + "/" + str(numberOfInsts) + "."); | |
print("\n\t[!] Processed INST block. Reading CARS block:"); | |
#CARS | |
for i in range(0, numberOfCars): | |
posX = struct.unpack('f', f.read(4))[0]; | |
posY = struct.unpack('f', f.read(4))[0]; | |
posZ = struct.unpack('f', f.read(4))[0]; | |
#Angles are in radians, convert to degrees | |
posA = math.degrees(struct.unpack('f', f.read(4))[0]); | |
vID = struct.unpack('i', f.read(4))[0]; | |
#PosX, PosY, PosZ, Angle, CarID, PrimCol, SecCol, ForceSpawn, Alarm, DoorLock, Unknown1, Unknown2 | |
carLines.append("%.5f, %.5f, %.5f, %.2f, %d, -1, -1, 0, 0, -1, -1" % (posX, posY, posZ, posA, vID)); | |
#Skip junk flags at end of CARS block (28 bytes) | |
f.seek(f.tell() + 28); | |
#print("\t\t[CARS] Read and appended entry " + str(i + 1) + "/" + str(numberOfCars) + "."); | |
print("\n\t[!] Processed CARS block."); | |
finally: | |
f.close(); | |
#Append output | |
lines = "inst\n" + "\n".join(instLines) + "\nend\n"; | |
lines += "cars\n" + "\n".join(carLines) + "\nend"; | |
outputFile = outputPath + file; | |
print("\n\t[!] Saving data to " + outputFile + "..."); | |
fp = open(outputFile, "w+"); | |
fp.write(lines); | |
fp.close(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Benjamin Williams | |
## <[email protected]> | |
## -- | |
## bipltool.py/pyc | |
import os | |
import sys | |
import struct | |
#Base path to read from | |
basePath = "T:\\gtasa\\data\\maps\\exported\\"; | |
#File to read from | |
file = "vegasn_stream6.ipl"; | |
#Open up the file | |
f = open(basePath + file, "rb"); | |
#INST and CARS block output | |
instLines = []; | |
carLines = []; | |
try: | |
header = f.read(4); | |
if header != b"bnry": | |
print("target file is not a binary ipl file."); | |
f.close(); | |
exit(1); | |
else: | |
print("target file is a binary ipl file."); | |
numberOfInsts = struct.unpack('i', f.read(4))[0]; | |
print("[header] INST block has " + str(numberOfInsts) + " items."); | |
#Skip unknown bytes (4 * 3) | |
f.seek(f.tell() + 4 * 3); | |
numberOfCars = struct.unpack('i', f.read(4))[0]; | |
print("[header] CARS block has " + str(numberOfCars) + " items."); | |
#Skip unknown bytes (4 * 1) | |
f.seek(f.tell() + 4); | |
offset = struct.unpack('i', f.read(4))[0]; | |
print(str(offset) + " is the offset for the INST block."); | |
#Skip junk data (11 * 4) | |
f.seek(f.tell() + (11 * 4)); | |
print("Read header values. Reading instance data."); | |
#INST | |
for i in range(0, numberOfInsts): | |
posX = struct.unpack('f', f.read(4))[0]; | |
posY = struct.unpack('f', f.read(4))[0]; | |
posZ = struct.unpack('f', f.read(4))[0]; | |
rotX = struct.unpack('f', f.read(4))[0]; | |
rotY = struct.unpack('f', f.read(4))[0]; | |
rotZ = struct.unpack('f', f.read(4))[0]; | |
rotW = struct.unpack('f', f.read(4))[0]; | |
objID = struct.unpack('i', f.read(4))[0]; | |
unk = struct.unpack('i', f.read(4))[0]; | |
flags = struct.unpack('i', f.read(4))[0]; | |
#ID, ModelName, Interior, PosX, PosY, PosZ, RotX, RotY, RotZ, RotW, LOD | |
instLines.append("%d, dummy, %d, %.5f, %.5f, %.5f, %.5f, %.5f, %.5f, %.5f, %d" % (objID, unk, posX, posY, posZ, rotX, rotY, rotZ, rotW, flags)); | |
#CARS | |
for i in range(0, numberOfCars): | |
posX = struct.unpack('f', f.read(4))[0]; | |
posY = struct.unpack('f', f.read(4))[0]; | |
posZ = struct.unpack('f', f.read(4))[0]; | |
#For some reason this needs negating and multiplying by 100... | |
posA = -struct.unpack('f', f.read(4))[0] * 100; | |
vID = struct.unpack('i', f.read(4))[0]; | |
#PosX, PosY, PosZ, Angle, CarID, PrimCol, SecCol, ForceSpawn, Alarm, DoorLock, Unknown1, Unknown2 | |
carLines.append("%.5f, %.5f, %.5f, %.2f, %d, -1, -1, 0, 0, -1, -1" % (posX, posY, posZ, posA, vID)); | |
#Skip junk flags at end of CARS block (28 bytes) | |
f.seek(f.tell() + 28); | |
finally: | |
f.close(); | |
#Append output | |
lines = "inst\n" + "\n".join(instLines) + "\nend\n"; | |
lines += "cars\n" + "\n".join(carLines) + "\nend"; | |
print(lines); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import os | |
basePath = "T:\gtasa\data\maps\\"; | |
folders = [ ".", "country", "generic", "interior", "LA", "leveldes", "SF", "vegas", "veh_mods", "exported2" ]; | |
targetTag = "inst"; | |
outputLines = ""; | |
for folder in folders: | |
files = os.listdir(basePath + folder); | |
filteredFiles = [file for file in files if file.endswith(".ipl")]; | |
for file in filteredFiles: | |
fp = open(basePath + folder + "\\" + file, "r"); | |
print("[" + basePath + folder + "\\" + file + "]"); | |
tagActive = False; | |
for line in fp: | |
if line.startswith(targetTag) and tagActive == False: | |
tagActive = True; | |
continue; | |
if tagActive == True: | |
if line.startswith("end"): | |
tagActive = False; | |
continue; | |
else: | |
outputLines += line; | |
fp.close(); | |
fp = open(basePath + "output-" + targetTag + ".txt", "w+"); | |
fp.write(outputLines); | |
fp.close(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment