Auto-Updater for TGE/TGB/TSE
by Tom Bushby · 07/03/2006 (11:13 am) · 51 comments
Download Code File
[ This resource was written using T2D Beta 3 1.1, and TGE 1.4. It has not been thoroughly tested on TSE. ]
Update 14 September 2006
Uploaded updated files. Includes fixes for several faults. I'll be updating the documentation to reflect the new changes as soon as possible. Please read the comments in the update.cs TorqueScript file for descriptions of variables.
Auto-Updater for TGE/TGB/TSE
This resource shows how you can easily use TorqueScript and C++ to create an auto-updater for your games. This resource utilises TorqueScript, C++, and PHP - and can be used along with SVN.
Alot of people want an easy way to let clients update their game files with a single click of a button, not having to worry about creating complex patches, and how to effectively combat the alteration of game files.
This auto-updater can help that. It compares game files from the client to official files on the server, using the industry standard MD5 hashing techniques (MD5 File resource by Dave Young).
How It Works
The auto-updater is very simple, it compares client MD5 hashes to server MD5 hashes of game files, and updates them accordingly.
1) Player requests game file updates from within game.
2) Client machine (Client) requests a list of game files and MD5 hashes from web server.
3) Client calculates MD5 hashes of local files and compares them to server hashes.
4) If hashes are found to be inequal, the client will put the local path of the file into an array for later processing.
5) Once all files are hashed, and the connection to the web server is terminated, the client will go through each record in the array and request the updated file.
- Client connects to a PHP script on the web server, posting information about client and requested file.
- If the client checks out, the server will stream down the requested file (includes Binary files.)
- Client strips headers and downloads file. (TCPObject Binary Transfer Resource (see below) by Dylan Sale.)
- Once downloaded, client will write the data to a file with the local path of the file. (TCPObject Binary Transfer Resource by Dylan Sale.)
- Stage 5 will repeat until all files are downloaded. (Option to stream multiple files (connections) included.)
6) Client has functions to let the game creator use GUI to show that the downloads are complete, and the game needs to be restarted for changes to take place (or perhaps the game could restart it's self? ;) )
Client / Server Requirements
- Client
The client needs nothing special for this updater to work. As long as TGE/TGB/TSE runs, you should be good to go.
- Server
The auto-updater allows for the game creator to keep official game files on different servers to official game servers or not. The auto-updater was also originally designed to work with an SVN repository directly. However, this direction was avoided, and instead allows the auto-updater to work with an SVN Repository or File Server.
While updating game files directly when connecting to a game server, and updating the files directly from the game server, would be nice in theory, I decided that this would not be advisable, due to load issues, and that using a Web Server to distribute files would be more friendly on the people who don't own super-sized servers which can handle hundreds of thousands of connections and stream files endlessly.
-- Web Server
The web server needs have PHP installed (recommended PHP 4 or PHP 5) to handle the PHP files and allow for the client to download stored files. Files can be stored locally, or on other servers. However, this server will stream the files to the client using the TCPObject Binary Transfer Resource by Dylan Sale, as well as use the PHP scripts provided.
-- [Optional] SVN
If the web server supports SVN, and it can be used from the command line, then the auto-updater can be used to along with it to enable quick updating of both official files and game files. Which means that the auto-updater will allow clients to download official files, yet allowing game creators to update their files quickly with SVN. There is no special code needed to use SVN, as long as you "Checkout" or "Update" the repository, and not directly have an repository that isn't accessable via the file structure / PHP.
Addition Resources
Before I go any further, I need to say Thank You! to both Dylan Sale and Dave Young for allowing me to combine their resources, and my own code, to create this auto-updater, and put it up as a resource. I would request that you contact them for any issues with their resources.
In order for you to use this resource, you will need to add in two very very simple resources into your TGE/TGB/TSE executable.
Firstly, the TCPObject Binary Resource by Dylan Sale is needed for Binary Transfer from Server to Client. You can find it here.
Secondly, the MD5 File Resource by Dave Young is needed for hashing the client's files. (Server files are handled by PHP.) You can find it here.
Adding in the TorqueScript auto-updater files
Once your executable has finished compiling with both the TCPObject Binary Transfer and MD5 File resources, it's time to add in the TorqueScript auto-updater files.
The auto-updater is a very small set of scripts, but has huge potential.
Grab the files update.cs and stream.cs in the /TorqueScript_Auto-Updater/ from the included compressed file. Copy them to your client scripts folder, or gameScripts folder, and exec() them in a main file, like game.cs
For TGB
In T2D/gameScripts/initializeT2D.cs, around line 9 add:
In starter.fps/client/init.cs, around line 85 add:
Calling Updates
To call updates from your game, just use the function updateClientDownload(). It will start the process of hashing files, and requesting updated files. Make sure you have exec()'d your update.cs or this will not work. ;)
Modifying the auto-updater to your tastes
Modifying the auto-updater to your game is very simple. In the top of update.cs lies a long list of variables which control how the updater works. These are documented and pretty simple to follow.
However, modifying the auto-updater to update your GUI is a bit more complex, as it requires writing code to update your GUI. This isn't hard. ;)
Insert your code for when the update finishes in finishUpdate(). It will be called when the update is complete.
Client Variables
There are a few very interesting client variables that you will want to use if you come to intergrate this resource into your game and GUI:
Server Implementation
This may appear slightly confusing, but it's actually really easy to setup a server ready to deploy updates.
-- File Serving
Place all your games files somewhere on the server, where the web server's user can access them. Such as /home/updater/svn/game/. If you don't have SSH access, and can't run a PHP script outside of your public_html directory: (i) Get a dedicated server or VPS, (ii) Get your server administrator to the run the below file, (iii) Place all your game files into a very secure directory in your public_html directory. (iii) is not advised nor supported.
-- Generating a list of hashes
In the included compressed file is a file, PHP_Server-Generate-Files/generatelist.php.
Just place that above the directory containing your game files. In my example, I would put it at /home/updater/svn/generatelist.php. Change line 133 to reflect the name of the directory containing your game files.
Run this script, it will echo out each directory as it processes it, represented by a full stop or dot (.). Once completed, it will create a file called testresults.txt. (You can change the name of that file on lines: 55 and 101.)
Copy and rename that file to allow your web server to serve it. Make sure it matchs up against the path in your updater.cs file on the client. I put mine in /home/updater/public_html.
-- Serving your files
Upload the file gameupdate.php under PHP_Web-Serving/ to your web server, somewhere like /home/updater/public_html. Make sure the path matchs the one in update.cs.
Make sure you edit the gameupdate.php variables at the top of the file to reflect your own server.
Limitations
There are a few known limitations that I have concluded:
- TCPObject disconnection methods take along time to disconnect. That's why there is the possibility of several connections per client. Reduce the number in update.cs to match your server hardware, and capabilities.
I think that's all for limitations, but I'll add more if more emerge.
Change Log
- Updated the TCPObject references to support the latest update of the TCP Object Binary Transfer Resource by Dylan Sale.
Testing
I have tested this auto-updater, and use it nearly once every two days, to update up to around 3000 files in an SVN repository, as my SVN client packed up. I've been getting stable streaming, and not once got a connection error.
However, the large file thing does come into play with two files which are extremely large, and cannot be downloaded.
Thanks
Thank you for reading, and I hoped you enjoyed this resource. If you have any questions or comments, please leave them below. :)
I don't think I have forgotten anything, but you never know...
Special thanks to Dylan Sale and Dave Young for their great resources.
Thank you,
Best Regards,
- Tom Bushby.
[ This resource was written using T2D Beta 3 1.1, and TGE 1.4. It has not been thoroughly tested on TSE. ]
Update 14 September 2006
Uploaded updated files. Includes fixes for several faults. I'll be updating the documentation to reflect the new changes as soon as possible. Please read the comments in the update.cs TorqueScript file for descriptions of variables.
Auto-Updater for TGE/TGB/TSE
This resource shows how you can easily use TorqueScript and C++ to create an auto-updater for your games. This resource utilises TorqueScript, C++, and PHP - and can be used along with SVN.
Alot of people want an easy way to let clients update their game files with a single click of a button, not having to worry about creating complex patches, and how to effectively combat the alteration of game files.
This auto-updater can help that. It compares game files from the client to official files on the server, using the industry standard MD5 hashing techniques (MD5 File resource by Dave Young).
How It Works
The auto-updater is very simple, it compares client MD5 hashes to server MD5 hashes of game files, and updates them accordingly.
1) Player requests game file updates from within game.
2) Client machine (Client) requests a list of game files and MD5 hashes from web server.
3) Client calculates MD5 hashes of local files and compares them to server hashes.
4) If hashes are found to be inequal, the client will put the local path of the file into an array for later processing.
5) Once all files are hashed, and the connection to the web server is terminated, the client will go through each record in the array and request the updated file.
- Client connects to a PHP script on the web server, posting information about client and requested file.
- If the client checks out, the server will stream down the requested file (includes Binary files.)
- Client strips headers and downloads file. (TCPObject Binary Transfer Resource (see below) by Dylan Sale.)
- Once downloaded, client will write the data to a file with the local path of the file. (TCPObject Binary Transfer Resource by Dylan Sale.)
- Stage 5 will repeat until all files are downloaded. (Option to stream multiple files (connections) included.)
6) Client has functions to let the game creator use GUI to show that the downloads are complete, and the game needs to be restarted for changes to take place (or perhaps the game could restart it's self? ;) )
Client / Server Requirements
- Client
The client needs nothing special for this updater to work. As long as TGE/TGB/TSE runs, you should be good to go.
- Server
The auto-updater allows for the game creator to keep official game files on different servers to official game servers or not. The auto-updater was also originally designed to work with an SVN repository directly. However, this direction was avoided, and instead allows the auto-updater to work with an SVN Repository or File Server.
While updating game files directly when connecting to a game server, and updating the files directly from the game server, would be nice in theory, I decided that this would not be advisable, due to load issues, and that using a Web Server to distribute files would be more friendly on the people who don't own super-sized servers which can handle hundreds of thousands of connections and stream files endlessly.
-- Web Server
The web server needs have PHP installed (recommended PHP 4 or PHP 5) to handle the PHP files and allow for the client to download stored files. Files can be stored locally, or on other servers. However, this server will stream the files to the client using the TCPObject Binary Transfer Resource by Dylan Sale, as well as use the PHP scripts provided.
-- [Optional] SVN
If the web server supports SVN, and it can be used from the command line, then the auto-updater can be used to along with it to enable quick updating of both official files and game files. Which means that the auto-updater will allow clients to download official files, yet allowing game creators to update their files quickly with SVN. There is no special code needed to use SVN, as long as you "Checkout" or "Update" the repository, and not directly have an repository that isn't accessable via the file structure / PHP.
Addition Resources
Before I go any further, I need to say Thank You! to both Dylan Sale and Dave Young for allowing me to combine their resources, and my own code, to create this auto-updater, and put it up as a resource. I would request that you contact them for any issues with their resources.
In order for you to use this resource, you will need to add in two very very simple resources into your TGE/TGB/TSE executable.
Firstly, the TCPObject Binary Resource by Dylan Sale is needed for Binary Transfer from Server to Client. You can find it here.
Secondly, the MD5 File Resource by Dave Young is needed for hashing the client's files. (Server files are handled by PHP.) You can find it here.
Adding in the TorqueScript auto-updater files
Once your executable has finished compiling with both the TCPObject Binary Transfer and MD5 File resources, it's time to add in the TorqueScript auto-updater files.
The auto-updater is a very small set of scripts, but has huge potential.
Grab the files update.cs and stream.cs in the /TorqueScript_Auto-Updater/ from the included compressed file. Copy them to your client scripts folder, or gameScripts folder, and exec() them in a main file, like game.cs
For TGB
In T2D/gameScripts/initializeT2D.cs, around line 9 add:
exec("~/gameScripts/update.cs");For TGE/TSEIn starter.fps/client/init.cs, around line 85 add:
exec("scripts/update.cs");Calling Updates
To call updates from your game, just use the function updateClientDownload(). It will start the process of hashing files, and requesting updated files. Make sure you have exec()'d your update.cs or this will not work. ;)
Modifying the auto-updater to your tastes
Modifying the auto-updater to your game is very simple. In the top of update.cs lies a long list of variables which control how the updater works. These are documented and pretty simple to follow.
However, modifying the auto-updater to update your GUI is a bit more complex, as it requires writing code to update your GUI. This isn't hard. ;)
Insert your code for when the update finishes in finishUpdate(). It will be called when the update is complete.
Client Variables
There are a few very interesting client variables that you will want to use if you come to intergrate this resource into your game and GUI:
Quote:$currentFileNumbers -> The variable which holds how many connections the client has open to the web server.
$totalConnectionsCur -> The variable which holds how many files have been sucessfully updated.
$stream[$currentFileNum] + $currentFileNum -> The variables which contain data about the currently updating files and the stream's information, such as local path to file.
Server Implementation
This may appear slightly confusing, but it's actually really easy to setup a server ready to deploy updates.
-- File Serving
Place all your games files somewhere on the server, where the web server's user can access them. Such as /home/updater/svn/game/. If you don't have SSH access, and can't run a PHP script outside of your public_html directory: (i) Get a dedicated server or VPS, (ii) Get your server administrator to the run the below file, (iii) Place all your game files into a very secure directory in your public_html directory. (iii) is not advised nor supported.
-- Generating a list of hashes
In the included compressed file is a file, PHP_Server-Generate-Files/generatelist.php.
Just place that above the directory containing your game files. In my example, I would put it at /home/updater/svn/generatelist.php. Change line 133 to reflect the name of the directory containing your game files.
Run this script, it will echo out each directory as it processes it, represented by a full stop or dot (.). Once completed, it will create a file called testresults.txt. (You can change the name of that file on lines: 55 and 101.)
Copy and rename that file to allow your web server to serve it. Make sure it matchs up against the path in your updater.cs file on the client. I put mine in /home/updater/public_html.
-- Serving your files
Upload the file gameupdate.php under PHP_Web-Serving/ to your web server, somewhere like /home/updater/public_html. Make sure the path matchs the one in update.cs.
Make sure you edit the gameupdate.php variables at the top of the file to reflect your own server.
Limitations
There are a few known limitations that I have concluded:
- TCPObject disconnection methods take along time to disconnect. That's why there is the possibility of several connections per client. Reduce the number in update.cs to match your server hardware, and capabilities.
I think that's all for limitations, but I'll add more if more emerge.
Change Log
- Updated the TCPObject references to support the latest update of the TCP Object Binary Transfer Resource by Dylan Sale.
Testing
I have tested this auto-updater, and use it nearly once every two days, to update up to around 3000 files in an SVN repository, as my SVN client packed up. I've been getting stable streaming, and not once got a connection error.
However, the large file thing does come into play with two files which are extremely large, and cannot be downloaded.
Thanks
Thank you for reading, and I hoped you enjoyed this resource. If you have any questions or comments, please leave them below. :)
I don't think I have forgotten anything, but you never know...
Special thanks to Dylan Sale and Dave Young for their great resources.
Thank you,
Best Regards,
- Tom Bushby.
#2
Before I wrote this, I wrote a simple one which just passed values back to Torque, such as path on webserver and path on local machine. Was very insecure, and hard to maintain. So I wrote this one instead. I wanted to use MD5 in the first place, but wasn't all that great at C++, so I used Dave Young's resource to manage it.
You might be interested to know that the TCPObject Resource was modified on July, 01, 2006 to pass a size of the file downloading to the C++ functions, so larger files (30MB) wouldn't get screwed up.
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4926
Thanks,
- Tom.
07/03/2006 (12:06 pm)
:)Before I wrote this, I wrote a simple one which just passed values back to Torque, such as path on webserver and path on local machine. Was very insecure, and hard to maintain. So I wrote this one instead. I wanted to use MD5 in the first place, but wasn't all that great at C++, so I used Dave Young's resource to manage it.
You might be interested to know that the TCPObject Resource was modified on July, 01, 2006 to pass a size of the file downloading to the C++ functions, so larger files (30MB) wouldn't get screwed up.
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4926
Thanks,
- Tom.
#3
07/20/2006 (12:14 pm)
problem fixed : 5/5
#4
I am using the GET command instead of POST because POST is not allowed on the files apparently.
07/20/2006 (1:19 pm)
edit : fixedI am using the GET command instead of POST because POST is not allowed on the files apparently.
#5
Seems your console is throwing some errors from your server.
Thanks,
- Tom.
07/22/2006 (1:43 am)
Is this fixed now? :)Seems your console is throwing some errors from your server.
Thanks,
- Tom.
#6
07/22/2006 (9:01 am)
Hmm, it still isn't working right, for some reason the web server is sending 184 byte files instead of the entire thing.
#7
Kyle, make sure the directories are good e.g., the paths in the results file created by generatelist.php relate to the same paths as in your game folder which is on the server. Also make sure the file that is requested to stream down the actual files for your game actually had the correct paths at the top of the file. :)
Edit : Assuming that the updater is creating files on your local system with correct paths and names, it must be your file that streams down the game files, that is the problem. Check the paths at the top of the file, and make sure they are correct. Also make sure that the file has the permissions to grab the game files. ;)
Edit : I saw you are using GET. If you're using get, make sure to edit the gameupdate.php to change all instances of $_POST to $_GET. :) That should solve your problem. Sorry I didn't see that earlier, I only saw the message before you edited it.
Thanks,
- Tom.
07/23/2006 (12:02 pm)
The resource to me seems to be cut off at:Quote:There is no special code needed to use SVN, as long as yHowever, I haven't edited it at all, and the last time I checked it was OK.
Kyle, make sure the directories are good e.g., the paths in the results file created by generatelist.php relate to the same paths as in your game folder which is on the server. Also make sure the file that is requested to stream down the actual files for your game actually had the correct paths at the top of the file. :)
Edit : Assuming that the updater is creating files on your local system with correct paths and names, it must be your file that streams down the game files, that is the problem. Check the paths at the top of the file, and make sure they are correct. Also make sure that the file has the permissions to grab the game files. ;)
Edit : I saw you are using GET. If you're using get, make sure to edit the gameupdate.php to change all instances of $_POST to $_GET. :) That should solve your problem. Sorry I didn't see that earlier, I only saw the message before you edited it.
Thanks,
- Tom.
#8
07/26/2006 (2:25 pm)
#9
Here are my files
07/26/2006 (3:15 pm)
Alright it connects, but isn't outputting anything when it compares file hashs and just disconnects afterwords. If I tell it to write the files to another directory it gets everything. If I modify a file, it doesn't detect it..Here are my files
#10
- Tom.
07/30/2006 (5:13 am)
I actually sent you an e-mail just after your post on the 26th. Not sure if you have it read it or not, but it contains some information about your problem and how to fix it.- Tom.
#11
Hopefully you are still around. :) Great resource.
I implemented the resource and after a little tweaking, manage to get it to work. However, I come across one issue that was mentioned by Kyle also. I can save files in sub-directories, but not the root directory (where the exe is located). A very quick look didn't turn up anything and I figured I'd ask you to see if you had an idea on where to start looking to be able to correct the issue.
Thanks,
Derk
09/14/2006 (11:58 am)
Tom,Hopefully you are still around. :) Great resource.
I implemented the resource and after a little tweaking, manage to get it to work. However, I come across one issue that was mentioned by Kyle also. I can save files in sub-directories, but not the root directory (where the exe is located). A very quick look didn't turn up anything and I figured I'd ask you to see if you had an idea on where to start looking to be able to correct the issue.
Thanks,
Derk
#12
I'm still around. :) Thanks.
I've experienced that issue, but only on some systems. The systems seemed to be mostly Window's machines running IIS + PHP. I fixed this issue, as well as a number of minor issues, and added some more stuff in as well, a little while ago.
Edit : Uploaded new files that should fix that issue. Please look carefully for any paths, variables and other functions that relate to the updating, logging or streaming process. Please note that these files are just uploaded as soon as I could, so comments may be missing, and documentation certainly needs to be updated.
Thanks,
- Tom.
09/14/2006 (12:51 pm)
Derk,I'm still around. :) Thanks.
I've experienced that issue, but only on some systems. The systems seemed to be mostly Window's machines running IIS + PHP. I fixed this issue, as well as a number of minor issues, and added some more stuff in as well, a little while ago.
Edit : Uploaded new files that should fix that issue. Please look carefully for any paths, variables and other functions that relate to the updating, logging or streaming process. Please note that these files are just uploaded as soon as I could, so comments may be missing, and documentation certainly needs to be updated.
Thanks,
- Tom.
#13
Works great. You even added my tweak to remove the main directory name from the file log.
It saves files in the root directory beautifully.
But... The saved file doesn't end up with the same hash as the master file so it downloads the file every time you update.
And, this may be beyond your needs, but do you have any ideas about how to update the torque exe file? The system won't let you save to it while it is running. Should I go a different route and have an external updating program or do you know a good way to integrate it into your resource?
Thanks,
Derk
09/15/2006 (10:07 am)
Tom,Works great. You even added my tweak to remove the main directory name from the file log.
It saves files in the root directory beautifully.
But... The saved file doesn't end up with the same hash as the master file so it downloads the file every time you update.
And, this may be beyond your needs, but do you have any ideas about how to update the torque exe file? The system won't let you save to it while it is running. Should I go a different route and have an external updating program or do you know a good way to integrate it into your resource?
Thanks,
Derk
#14
Glad that it works.
I'm not sure why the files would not have the same hash as the ones on the master server, I will have to look into that in more detail. Check for any whitespace at the start or end of the file which may cause a different MD5 hash.
Torque can't update the EXE while it's running. A good idea might be to have a seperate EXE for updating alone, that way it can update the main EXE, and the main can update the updater EXE. :)
I'll look into the MD5 hash issue as soon as I have time.
Thanks,
- Tom.
09/15/2006 (10:38 am)
Derk,Glad that it works.
I'm not sure why the files would not have the same hash as the ones on the master server, I will have to look into that in more detail. Check for any whitespace at the start or end of the file which may cause a different MD5 hash.
Torque can't update the EXE while it's running. A good idea might be to have a seperate EXE for updating alone, that way it can update the main EXE, and the main can update the updater EXE. :)
I'll look into the MD5 hash issue as soon as I have time.
Thanks,
- Tom.
#15
Found it. You are not stripping the following out from the top of the files:
Thanks,
Derk
09/15/2006 (11:05 am)
Tom,Found it. You are not stripping the following out from the top of the files:
Proxy-Connection: Keep-Alive Keep-Alive: 3 Content-Type: application/octet-streamThere is an empty line at the end of that code snip.
Thanks,
Derk
#16
I'm pretty sure you can overcome that by using something like:
Hope that helps,
- Tom.
09/15/2006 (11:12 am)
Derk,I'm pretty sure you can overcome that by using something like:
$Pref::Updater::StripHeaderFirstLine = "Keep-Alive:"; $Pref::Updater::StripHeaderSecondLine = "Content-Type:"; $Pref::Updater::StripHeaderThird = "";In update.cs.
Hope that helps,
- Tom.
#17
I understand now that you changed that process (didn't understand without instructions). However, I fixed it by using the previous version's "Stream::onLine." What was your reason for changing it and adding the three variables?
Thanks,
Derk
09/15/2006 (11:37 am)
Tom,I understand now that you changed that process (didn't understand without instructions). However, I fixed it by using the previous version's "Stream::onLine." What was your reason for changing it and adding the three variables?
Thanks,
Derk
#18
Glad you got it working.
The reason it got changed to three was because 1 or more headers on the system I was working on were returning blank, so 2 header checks would not cut it, so I increased it to 3.
Thanks,
- Tom.
09/15/2006 (12:03 pm)
Derk,Glad you got it working.
The reason it got changed to three was because 1 or more headers on the system I was working on were returning blank, so 2 header checks would not cut it, so I increased it to 3.
Thanks,
- Tom.
#19
Humming along nicely. I've added a preliminary step that checks a file for the current version to see if an update is needed (along with a way to force the update if it didn't succeed in copying the files even though it updated the version number).
Anyway, I'm working on the gui to let the user know what is happening. I've adapted the loadingGui for my purposes. Everything works great except for when the system is getting the local md5 strings and comparing them. It seems to be so much work that Torque can't update the gui or move the mouse cursor.
Do you know of a way to tell the system to slow down and update the interface?
Thanks,
Derk
09/16/2006 (8:09 am)
Tom,Humming along nicely. I've added a preliminary step that checks a file for the current version to see if an update is needed (along with a way to force the update if it didn't succeed in copying the files even though it updated the version number).
Anyway, I'm working on the gui to let the user know what is happening. I've adapted the loadingGui for my purposes. Everything works great except for when the system is getting the local md5 strings and comparing them. It seems to be so much work that Torque can't update the gui or move the mouse cursor.
Do you know of a way to tell the system to slow down and update the interface?
Thanks,
Derk
#20
Sorry for slow reply.
I'm not sure how to slow that process down, or seperate it, at this time. Though if someone else could come up with a solution that would be great.
Thanks,
- Tom.
09/18/2006 (1:56 pm)
Derk,Sorry for slow reply.
I'm not sure how to slow that process down, or seperate it, at this time. Though if someone else could come up with a solution that would be great.
Thanks,
- Tom.

Torque Owner Stefan Lundmark