Even though I said this, ill just throw some random stuff together (without thinking about its implementation) that you can review:
local RW_TYPE = { -- print(decToHex(bytesToData("ui",string.char(0xFF, 0xFF, 0x03, 0x18))))
[1] = 'rwDATA',
[2] = 'rwSTRING',
[3] = 'rwEXTENSION',
[6] = 'rwTEXTURE',
[7] = 'rwMATERIAL',
[8] = 'rwMATERIALLIST',
[14] = 'rwFRAMELIST',
[15] = 'rwGEOMETRY',
[16] = 'rwCLUMP',
[20] = 'rwATOMIC',
[26] = 'rwGEOMETRYLIST',
[1294] = 'rwMATERIALSPLIT',
[39056126] = 'rwFRAME',
};
local lBytesToData = bytesToData
local lDecToHex = decToHex
local lCreateCipher = createCipher
local lCipher = cipher
local function readChunkHeaderInfo(file, c) -- an exception is needed so that you are at the beginning of the chunk @c = current_position
local c = c and c or 0
local ChunkHeaderInfo = { rwType = ''; bytes = ''; version = 0; buildings = '' };
file:setPos(c)
ChunkHeaderInfo.rwType = lBytesToData('ui', file:read(4)); file:setPos(c+4)
ChunkHeaderInfo.bytes = lBytesToData('ui', file:read(4)); file:setPos(c+8)
ChunkHeaderInfo.version = lDecToHex(lBytesToData('ui', file:read(4))); file:setPos(c+12)
ChunkHeaderInfo.buildings = lBytesToData('ui', file:read(4));
local rwString = RW_TYPE[ChunkHeaderInfo.rwType]
if rwString then
ChunkHeaderInfo.rwType = rwString
end
return ChunkHeaderInfo
end
local function readGeometryInfo(file, c) -- an exception is necessary for you to be at the beginning of RWDATA GEOMETRY @c = current_position
local c = c and c or 0
local rwGeometryInfo = { rwType = ''; bytes = ''; version = 0; FACES = 0, VERTEX = 0 };
file:setPos(c)
rwGeometryInfo.rwType = lBytesToData('ui', file:read(4)); file:setPos(c+4)
rwGeometryInfo.bytes = lBytesToData('ui', file:read(4)); file:setPos(c+8)
rwGeometryInfo.version = lDecToHex(lBytesToData('ui', file:read(4)));
-- skipping flags and some bull:~
file:setPos(c+12+4)
rwGeometryInfo.FACES = lBytesToData('ui', file:read(4))
file:setPos(c+12+8)
rwGeometryInfo.VERTEX = lBytesToData('ui', file:read(4))
local rwString = RW_TYPE[rwGeometryInfo.rwType]
if rwString then
rwGeometryInfo.rwType = rwString
end
return rwGeometryInfo
end
local function ENCODE(path, key)
local file = fileOpen(path)
--
local buffer = ''
local pos = 48 + (readChunkHeaderInfo(file, 36).bytes) + 12 + 16 -- skip some initial data as well at FrameList.
local data = { key = key, start = 0, size = 512, blocks = {} } -- encryption data
--
fileSetPos(file, 0)
buffer = fileRead(file, pos + 12 + 4) -- we read everything until the first geometry
--
local newpos = pos
--
local i = 1
local t = getTickCount()
--
data.start = newpos+12+4
while true do
local ChunkHeaderInfo = readChunkHeaderInfo(file, newpos)
if ChunkHeaderInfo.rwType ~= 'rwGEOMETRY' then
break
else
fileSetPos(file, newpos)
if ChunkHeaderInfo.bytes >= 512 then
local part = fileRead(file, 512)
-- part=encodeCaesarXor(part, 128)
local self = lCreateCipher('rc4')
part = lCipher(self, part)
buffer = buffer..part
fileSetPos(file, newpos+512+12+4)
buffer = buffer .. fileRead(file, (ChunkHeaderInfo.bytes+12)-512)
else
buffer = buffer .. fileRead(file, ChunkHeaderInfo.bytes+12)
end
--
table.insert(data.blocks, { newpos, ChunkHeaderInfo.bytes })
newpos=newpos+(ChunkHeaderInfo.bytes+12)
i=i+1
end
end
--
buffer = buffer .. fileRead(file, file.size-newpos)
--
fileClose(file)
local file = fileCreate('1.dff')
fileWrite(file, buffer)
fileClose(file)
--
local file = fileCreate('file.key')
fileWrite(file, inspect(data))
fileClose(file)
--
print('ms: '..(getTickCount()-t))
end
ENCODE('infernus.dff', '1')
-- table from file
data = {
blocks = { { 8287, 492453 }, { 500752, 164001 }, { 664765, 88344 }, { 753121, 52054 }, { 805187, 356965 }, { 1162164, 1675 }, { 1163851, 521 }, { 1164384, 2997 }, { 1167393, 6039 }, { 1173444, 18268 }, { 1191724, 1519 }, { 1193255, 88956 }, { 1282223, 21275 }, { 1303510, 12068 }, { 1315590, 48581 }, { 1364183, 12180 }, { 1376375, 90521 }, { 1466908, 48349 }, { 1515269, 17305 }, { 1532586, 9920 }, { 1542518, 8002 }, { 1550532, 1342 }, { 1551886, 1339 }, { 1553237, 7030 }, { 1560279, 4238 }, { 1564529, 7986 }, { 1572527, 7986 }, { 1580525, 41149 }, { 1621686, 42308 }, { 1664006, 89259 }, { 1753277, 89259 }, { 1842548, 32581 }, { 1875141, 120775 }, { 1995928, 106716 }, { 2102656, 192384 }, { 2295052, 2858 }, { 2297922, 195903 }, { 2493837, 2857 }, { 2496706, 199616 }, { 2696334, 2858 }, { 2699204, 186695 }, { 2885911, 57242 }, { 2943165, 162669 }, { 3105846, 148930 }, { 3254788, 3673 }, { 3258473, 47286 }, { 3305771, 29240 }, { 3335023, 3498 }, { 3338533, 200358 }, { 3538903, 39399 }, { 3578314, 99764 }, { 3678090, 75284 }, { 3753386, 99764 }, { 3853162, 75284 }, { 3928458, 5839 }, { 3934309, 5958 }, { 3940279, 1778 } },
key = "1",
size = 512,
start = 8303
}
local function DECODE(path, key)
local file = fileOpen(path)
--
local buffer = fileRead(file, data.start) -- we read everything until the first geometry
--
local newpos = data.blocks[1][1]
--
local i = 1
local t = getTickCount()
--
data.start = newpos+12+4
for i, v in ipairs(data.blocks) do
fileSetPos(file, newpos)
if v[2] >= 512 then
local part = fileRead(file, 512)
-- part=decodeCaesarXor(part, 128)
local self = lCreateCipher('rc4')
part = lCipher(self, part)
buffer = buffer..part
fileSetPos(file, newpos+512+12+4)
buffer = buffer .. fileRead(file, (v[2]+12)-512)
else
buffer = buffer .. fileRead(file, v[2]+12)
-- fileSetPos(file, newpos+12+4)
end
--
newpos=newpos+(v[2]+12)
i=i+1
end
--
buffer = buffer .. fileRead(file, file.size-newpos)
--
fileClose(file)
local file = fileCreate('2.dff')
fileWrite(file, buffer)
fileClose(file)
--
print('ms: '..(getTickCount()-t))
end
DECODE('infernus.dff', '1')