Page 1 of 1

Packet 0xdd (Compressed Gump). Help!

Posted: Fri Jan 08, 2010 5:57 am
by RonaldoBRILHA
Hi Guys,

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 Description:

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;
		}
Source: http://www.runuo.com/forums/third-party ... -0xdd.html

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;
Source: UO Machine Source Code

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

Source: http://iris.schattenkind.net/svn/branch ... t.gump.lua