I´m trying to decode this gump in c language. Can someone help me?
My Code:
Code: Select all
int compressed_gump(char *buf, int len) // 0xdd
int PlayerSerial,GumpID,x,y,CLen,DLen,size;
size = unpack16(buf+1);
PlayerSerial = unpack32(buf+3);
GumpID = unpack32(buf+7);
x = unpack32(buf+11);
y = unpack32(buf+15);
CLen = unpack32(buf+19);
if (CLen < 4)
{
LogPrint(3, "[ERROR] Compress Length < 4.");
return 0;
}
CLen -= 4;
if((28 + CLen) > (size))
{
LogPrint(3, "[ERROR] Bad Compressed Gumpdata !");
return 0;
}
DLen = unpack32(buf+23);
return 0;
}
Packet Name: Compressed Gump
Last Modified: 2009-09-10 16:06:57
Modified By: Grin
Packet: 0xDD
Sent By: Server
Size: variable
Packet Build
BYTE[1] Cmd
BYTE[2] len
BYTE[4] Player Serial
BYTE[4] Gump ID
BYTE[4] x
BYTE[4] y
BYTE[4] Compressed Gump Layout Length (CLen)
BYTE[4] Decompressed Gump Layout Length (DLen)
BYTE[CLen-4] Gump Data, zlib compressed
BYTE[4] Number of text lines
BYTE[4] Compressed Text Line Length (CTxtLen)
BYTE[4] Decompressed Text Line Length (DTxtLen)
BYTE[CTxtLen-4] Gump's Compressed Text data, zlib compressed
Subcommand Build
N/A
Notes
text lines is in Big-Endian Unicode formate, not NULL terminated
loop:
BYTE[2] Length
BYTE[Length*2] text
endloop
Default level for decompresion
I Founded some open sources . But my dev is in C++.
C# code
Code: Select all
private void CompressedGump( PacketReader pvSrc ) {
int serial = pvSrc.ReadInt32();
int dialogID = pvSrc.ReadInt32();
int x = pvSrc.ReadInt32();
int y = pvSrc.ReadInt32();
string layout = GetCompressedReader( pvSrc ).ReadString();
string[] text = new string[pvSrc.ReadInt32()];
pvSrc = GetCompressedReader( pvSrc );
for ( int i = 0; i < text.Length; i++ ) {
text[i] = pvSrc.ReadUnicodeString( pvSrc.ReadUInt16() );
}
}
public PacketReader GetCompressedReader( PacketReader pvSrc ) {
if ( m_CompBuffer == null ) {
m_CompBuffer = new byte[0x1000];
}
int num = pvSrc.ReadInt32();
if ( num == 0 ) {
return new PacketReader( m_CompBuffer, 0, 3, false, 0, "Gump Subset" );
}
int destLength = pvSrc.ReadInt32();
if ( destLength == 0 ) {
return new PacketReader( m_CompBuffer, 0, 3, false, 0, "Gump Subset" );
}
byte[] source = pvSrc.ReadBytes( num - 4 );
if ( destLength > m_CompBuffer.Length ) {
m_CompBuffer = new byte[( destLength + 0xfff ) & -4096];
}
Zlib.Unpack( m_CompBuffer, ref destLength, source, source.Length );
PacketReader reader = new PacketReader( m_CompBuffer, 0, destLength, true, 0, "Gump Subset" );
reader.Seek( 0, SeekOrigin.Begin );
return reader;
}
C# [2] code
Code: Select all
case 0xDD: //generic gump
int serialdd = packet[3] << 24 | packet[4] << 16 | packet[5] << 8 | packet[6];
int iddd = packet[7] << 24 | packet[8] << 16 | packet[9] << 8 | packet[10];
int xdd = packet[11] << 24 | packet[12] << 16 | packet[13] << 8 | packet[14];
int ydd = packet[15] << 24 | packet[16] << 16 | packet[17] << 8 | packet[18];
int compressLendd = packet[19] << 24 | packet[20] << 16 | packet[21] << 8 | packet[22];
if (compressLendd <= 4) return;
else compressLendd -= 4;
int decompressLendd = packet[23] << 24 | packet[24] << 16 | packet[25] << 8 | packet[26] + 1;
byte[] decompresseddd = new byte[decompressLendd];
byte[] compresseddd = new byte[compressLendd];
Buffer.BlockCopy(packet, 27, compresseddd, 0, compressLendd);
int success;
//if (IntPtr.Size == 8) success = Win32.uncompress64(decompresseddd, ref decompressLendd, compresseddd, compressLendd);
success = Win32.uncompress32(decompresseddd, ref decompressLendd, compresseddd, compressLendd);
if (success != 0)
{
Log.LogDataMessage(client, packet, "*** Error decompressing gump layout:");
return;
}
string layoutdd = ASCIIEncoding.ASCII.GetString(decompresseddd).TrimEnd('\0');
int offsetdd = 27 + compressLendd;
int linesdd = packet[offsetdd] << 24 | packet[offsetdd + 1] << 16 | packet[offsetdd + 2] << 8 | packet[offsetdd + 3];
compressLendd = packet[offsetdd + 4] << 24 | packet[offsetdd + 5] << 16 | packet[offsetdd + 6] << 8 | packet[offsetdd + 7];
string[] textdd = new string[linesdd];
if (compressLendd > 4)
{
compressLendd -= 4;
compresseddd = new byte[compressLendd];
Buffer.BlockCopy(packet, offsetdd + 12, compresseddd, 0, compressLendd);
decompressLendd = packet[offsetdd + 8] << 24 | packet[offsetdd + 9] << 16 | packet[offsetdd + 10] << 8 | packet[offsetdd + 11] + 1;
decompresseddd = new byte[decompressLendd];
//if (IntPtr.Size == 8) success = Win32.uncompress64(decompresseddd, ref decompressLendd, compresseddd, compressLendd);
success = Win32.uncompress32(decompresseddd, ref decompressLendd, compresseddd, compressLendd);
if (success != 0)
{
Log.LogDataMessage(client, packet, "*** Error decompressing gump strings:");
return;
}
offsetdd = 0;
int lendd = 0;
for (int x = 0; x < linesdd; x++)
{
lendd = (decompresseddd[offsetdd] << 8 | decompresseddd[offsetdd + 1]) * 2;
offsetdd += 2;
textdd[x] = UnicodeEncoding.BigEndianUnicode.GetString(decompresseddd, offsetdd, lendd);
offsetdd += lendd;
}
}
IncomingPackets.OnGenericGump(client, serialdd, iddd, xdd, ydd, layoutdd, textdd);
return;
LUA Code
Code: Select all
-- compressed Gump
function gPacketHandler.kPacket_Compressed_Gump () --0xDD
local input = GetRecvFIFO()
local popped_start = input:GetTotalPopped()
local id = input:PopNetUint8()
local size = input:PopNetUint16()
local newgump = {}
newgump.playerid = input:PopNetUint32()
newgump.dialogId = input:PopNetUint32()
newgump.x = input:PopNetUint32()
newgump.y = input:PopNetUint32()
newgump.Length_CompressedData = input:PopNetUint32() - 4
newgump.Length_Data = input:PopNetUint32()
printdebug("net",sprintf("NET: Length_CompressedData=%d Length_UncompressedData=%d\n",newgump.Length_CompressedData,newgump.Length_Data))
if (28 + newgump.Length_CompressedData > size) then
printf("NET: BROKEN - kPacket_Compressed_Gump packet, compressed gumplen = 0x%08x\n",newgump.Length_CompressedData)
print("Error: Server Sends bad Compressed Gumpdata ! Please report.")
print("FATAL ! kPacket_Compressed_Gump -> forced Crash")
NetCrash()
end
--- Data Part ---
local decompressed = CreateFIFO()
-- pop and decompress data into decompress fifo
input:PeekDecompressIntoFifo(newgump.Length_CompressedData,newgump.Length_Data,decompressed)
-- skip compressed part (peeked)
input:PopRaw(newgump.Length_CompressedData)
newgump.Data = decompressed:PopFilledString(decompressed:Size())
-- and clear the decompress fifo for later usage
decompressed:Clear()
-- WARNING strange -4 on compression ahead (see runuo2 source)
--- Textlines Part ---
newgump.numTextLines = input:PopNetUint32()
if (newgump.numTextLines ~= 0) then
newgump.Length_CompressedTextLines = input:PopNetUint32() - 4
newgump.Length_TextLines = input:PopNetUint32()
-- pop and decompress data into decompress fifo
input:PeekDecompressIntoFifo(newgump.Length_CompressedTextLines,newgump.Length_TextLines,decompressed)
-- skip compressed part (peeked)
input:PopRaw(newgump.Length_CompressedTextLines)
-- print gumpdata
for k,v in pairs(newgump) do printdebug("gump",sprintf("newgump.%s = ",k),v) end
local textlen = 0
newgump.textline = {}
newgump.textline_unicode = {}
--Index 0 because Serverside Gump Commands use this Index as textline references
for i = 0,newgump.numTextLines-1 do
textlen = decompressed:PopNetUint16()
printdebug("gump","reading text line ",i," with length ",textlen)
newgump.textline[i],newgump.textline_unicode[i] = UniCodeDualPop(decompressed,textlen)
printdebug("gump",sprintf("newgump.textline[%d](len=%d)=\n",i,textlen),newgump.textline[i])
end
end
decompressed:Destroy()
if ( (input:Size() >= 4) and (input:GetTotalPopped()-popped_start < size) ) then
local unknownterminator=input:PopNetUint32()
end
local dialog = GumpParser(newgump)
NotifyListener("Hook_OpenServersideGump",dialog,newgump.playerid,newgump.dialogId,newgump.Length_Data,true,newgump)
end