After sending a line you start polling for the number of bytes at the port every 1 ms, you do a read every time and check for your ack character. You do not really need to run the read and check operation unless the number of bytes function says the required number of bytes is present (is it just one character?)...that will save some time.
If the reply may consist of more than just one character your code is likely to fail as it is now..If you know the length of the reply check that the number of bytes available matches that number. If the length can vary you need to check the number of bytes, wait for some time and then check if it's the same..if it's the same and non-zero you know that the reply has been received (the wait must be just a bit m
ore than the inter-byte time)...then read it and check if it contains the character.
The line picking does not us emuch time, that's OK. Try removing all the timer, data sent etc. code when testing, you can add that later if you see that things work OK without them.
As commented by others you really use locals the wrong way. My guess is that you have experience with textual languages and think of them as variables...they are not. In G the variable is the wire. Almost all the locals you use could and should be replaced by wires or shift-registers. The sequence structures used can be replaced by flow controlled execution, makes it much more readable.
When you run the download, have you checked how many times the read ACK loop actually runs? If there never is a reply the first 20 ms anyway I would just do an inital wait of 20ms after sending the line..prior to starting the check for the ack.