Ghost’s blog » Uncategorized

December 8, 2007

The first 64 bit bug - SOLVED

The first 64 bit bug - SOLVED

There’s that neat server information box at the upper left on the main page. Its name is si2. How does it work?

There’s a PHP script that queries information from the given address in the same way that the game does when doig the “quick refresh”. The server response contains couple dozen bytes of data including the server name, numbe of players and such. The PHP script also queries detailed information about players, such as kills and onlinetime. The general information about the server can be fitted to one UDP packet, which are limited to 1400 bytes, but detailed player information could take more than 1400 bytes and it’d be splitted to multiple packets. This brings up some issues about the UDP protocol and how packets flow through the mysterious ‘net. The packet header must contain information about whether all the data was fitted in one packet or if there are multiple packets.

The server query protocol is described at http://developer.valvesoftware.com/wiki/Server_Queries#Protocol

The 64 bit bug is in the PHP script’s way of handling the packet header information.

This is the code block in file class_serverspy.php. The original code block is written by Daniel Luft, but it’s been used by Tim te Beek in si2. The code is GPL’d, so I’m not breaking the law by fixing it :)

The original lines have been commented by #, followed by the fixed lines.

   // 4 byte packet header
   $header = unpack("Nint", substr($cache, 0, 4));
   $packet_type = sprintf("%u", $header['int']);

#   if($packet_type == 0xFFFFFFFF)
   if($packet_type == sprintf("%u", -1))
   {
    // single packet
   }
#   elseif($packet_type == 0xFEFFFFFF)
   elseif($packet_type == sprintf("%u", -2))
   {
    // multi packets
   }

You can see that in the code the header information is taken from the full data, stored in $cache, and converted to integer value by unpack(”Nint”, …) where the “N” means “unsigned long (always 32 bit, big endian byte order)” [ http://fi2.php.net/pack ] and the “int” is the index name in the resulting associative array.

The next code line, $packet_type = sprintf(…), unnecessarily converts the integer value to integer value again. The “unnecessary” convert could have something to do when there is no data at all or something.

The following comparisons, if($packet_type == 0xFFFFFFFF), are the bug. On 32 bit system 0xFFFFFFFF is -1. On 64 bit system the value gets coverted to 0xFFFFFFFF00000000, which is something else. Big endian and little endian stuff on top of that and it’s all messed up. Nobody knows what the real value is after that :)

After both of the comparisons have failed because of the same cause, the PHP script thinks it got false data and stops there.

The fix is to compare against expected “real” value, which has been passed through the same sprintf() function to make sure that the values are in the same comparable format.

August 3, 2007

Assembly ‘07

The only way to catch the feel of the party is neat panorama. Here it is.

Assembly ‘07 panorama

Rolling Stones at Helsinki Olympic Stadium

Rolling Stones in Helsinki

Stadion on fire

They were playing at Olympic Stadium. In the end spectacle they relly light up the stadium. The stadium is full scale sports arena - described as the most beautiful in the world. You can see the fireworks were really big. On the right side of the image you see the characteristic stadium tower being lit by the fireworks.

Here’s video clip outside of the stadium. Sound quality is good as you can hear. The video quality is not as bad as it seems, but something happens when it gets on screen. The red dots in the sky are hot air balloons.

Stadion on fire

March 16, 2007

FPS kills faster than a bullet

The game started to CTD (crash to desktop) on me lately. Before that it seemed that the game was getting heavier and heavier and FPS was slowly going down. There wasn’t good explanation why it was happening. Everything had been the same for year(s). The change in gameplay was actually so small, that I hardly noticed any difference in normal play. Only CTDs got me doubt that everything wasn’t fine anymore.

The problem turned out to be my display adapter, Radeon 9800 Pro. More specifically it was its passive cooler that wasn’t functioning efficiently anymore. The heat sink wasn’t firmly attached to the GPU because some screws had got loose.

At least that’s how it seemed.

Tilting the loose heat sink on R9800Pro

[See how the loose heat sink could be tilted]

I’m yet to confirm that everything is working good again. Actually I already got one CTD after fixing the cooler. That might be because the GPU is already f’d up.

[next day]

It’s not the GPU. I got CTD with another R9800Pro. It could be something in the mainboard. When installing chipset drivers (Nforce3, v5.11) it throws bluescreen on ethernet drivers section. I got ethernet drivers (part of the chipset, “integrated” so to speak) installed separately, though.

Tomorrow I’ll downgrade chipset drivers to v5.10 and hope it’ll work better. Obviously there’s something wrong somewhere, beucase the game wasn’t crashing a month ago, but now it does.

[next day]

Downgrading chipset drivers didn’t help. I tried running CPU and memory stress programs, but I didn’t get the system to crash. However, right after I started CS:S and started to play I got BSOD (blue screen of death), which had never happened before. It seems that something is overheating, but when I immediately opened the chassis after the crash all components were just hand warm.

It could be that the CS:S installation itself has somehow managed to mess itself, but it’s quite long shot already. It seems that I’m stuck with low FPS for now.