dload.c: Explicit declare functions returning void
[m6809-computer-tools:dload-server.git] / dload.c
1 /*  DLOAD                  16 Jan 88           Burt Mitchell               */
2 /*                                                                         */
3 /*  Host software for an PC compatible to send files to a                  */
4 /*  Color Computer using the DLOAD command.                                */
5 /*  The Coco must be running Extended Color Basic v1.1 or OLDER            */
6
7 /*  This program uses 1200 baud as it is the default for the Coco.  It is  */
8 /*  configured to use the PC's com1: port. To change this you will have to */
9 /*  edit the procedures transmit_char() and receive_char().                */
10
11 /*  This program has not been tested in the DLOADM mode as I have no way   */
12 /*  of getting a Coco machine language routine into the PC in the first    */
13 /*  place.                                                                 */
14
15 /*  To operate DLOAD:                                                      */
16 /*  on the PC enter     DLOAD filename.ext a                               */
17 /*  the PC will inform you that it is waiting.                             */
18 /*  on the Coco enter   DLOAD                                              */
19
20 /* Modified for use with unix by Bryan Clingman (bac@realtimeweb.com)      */
21 /* 3-Jun-1997                                                                                                                      */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26
27 #define true    1
28 #define false   0
29 #define ok              1
30 #define bad             0
31
32 /* literals for the DLOAD protocol */
33
34 #define file_req        0x8A
35 #define block_req       0x97
36 #define NAK                     0xDE
37 #define ACK                     0xC8
38 #define EOT                     0xBC
39 #define ABORT           0xBC
40 #define ASCII           0xFF
41 #define BINARY          0x00
42 #define BASIC           0x00
43 #define ML                      0x02
44 #define block_size      127
45
46 unsigned char   chksum,
47                                 file_type,
48                                 asc_flag,
49                                 proceed;
50 unsigned char   rx_char,
51                                 status;
52 char                    *tx_name;
53 char                    *port;
54 FILE                    *infile;
55 FILE                    *fp;
56
57 void transmit_char(unsigned char tx_char)
58 {
59         fputc(tx_char, fp);
60 }
61
62 void receive_char()
63 {
64         rx_char = fgetc(fp);
65         if (rx_char == ABORT)
66         {
67                 printf("transfer aborted by target. \n");
68                 exit(1);
69         }
70 }
71
72 int main(int argc, char *argv[])
73 {
74         if (argc < 4)
75         {
76                 printf("usage: DLOAD [filename.ext] [A or B] [port]\n");
77                 exit(1);
78         }
79
80         tx_name = argv[1];
81
82         if ((*argv[2] == 'B') || (*argv[2] == 'b'))
83         {
84                 file_type = ML;
85                 asc_flag = BINARY;
86                 infile = fopen(tx_name,"rb");
87         }
88         else
89                 if ((*argv[2] == 'A') || (*argv[2] == 'a'))
90                 {
91                         file_type = BASIC;
92                         asc_flag = ASCII;
93                         infile = fopen(tx_name,"r");
94                 }
95                 else
96                 {
97                         printf("unknown file type \n");
98                         exit(1);
99                 }
100
101         if (infile == NULL)
102         {
103                 printf("cant open the file to be transmitted \n");
104                 exit(1);
105         }
106
107         port = argv[3];
108         init_port();
109
110         /* wait for the coco to start the transfer */
111
112         while (rx_char != file_req)
113                 receive_char();
114
115         proceed = true;
116
117         /* proceed with the file transfer */
118         while (proceed == true)
119         {
120                 /* get the file name from the coco. We arent using it but */
121                 /* it's part of the protocol. */
122
123                 transmit_char(file_req);
124
125                 rcv_file_name();
126
127                 /* tell the coco about the file it will receive. */
128
129                 initiate_transfer();
130
131                 /* now send the file */
132
133                 send_file();
134
135                 if (status == ok)
136                 {
137                         proceed = false;
138                 }
139                 else
140                 {
141                         proceed = false;
142                         printf("file not transmitted successfully \n");
143                 }
144         }
145         return 0;
146 }
147
148
149 void initiate_transfer()
150 {
151         chksum = (file_type ^ asc_flag);
152         transmit_char(ACK);
153         transmit_char(file_type);
154         transmit_char(asc_flag);
155         transmit_char(chksum);
156 }
157
158 void rcv_file_name()
159 {
160         char    count,
161                         filename[9],
162                         sum;
163
164         filename[8] = 0;
165         count = 0;
166         while (count <= 7)
167         {
168                 receive_char();
169                 filename[count] = rx_char;
170                 chksum = (chksum ^ rx_char);
171                 ++count;
172         }
173
174         receive_char();
175         sum = rx_char;
176
177         printf("target requested %s \n",&filename);
178
179         if (sum != chksum)
180         {
181                 printf("filename checksum bad. \n");
182                 status = bad;
183         }
184         else
185                 status = ok;
186 }
187
188 void send_file()
189 {
190         int                             count,
191                                         j;
192         char                    tx_flag,
193                                         xfer_done,
194                                         first_time,
195                                         send_new_block;
196         unsigned char   file_char[130],
197                                         xfer_length,
198                                         sum,
199                                         block_num,
200                                         old_block_num;
201         long int                total_xfer;
202
203         /**/
204
205         first_time = true;
206         total_xfer = 0;
207         xfer_length = 0;
208         xfer_done = false;
209         tx_flag = true;
210
211         while (tx_flag == true)
212         {
213                 send_new_block = true;
214
215                 while (rx_char != block_req)
216                         receive_char();
217
218                 transmit_char(block_req);
219
220                 chksum = 0;
221
222                 /* get the MSByte of the block number */
223
224                 receive_char();
225                 chksum = (chksum ^ rx_char);
226                 block_num = (rx_char << 7);
227
228                 /* get the LSByte of the block number */
229
230                 receive_char();
231                 chksum = (chksum ^ rx_char);
232                 block_num = (rx_char | block_num);
233
234                 /* should we retransmit the previous block? */
235
236                 if (first_time == false)
237                         if (block_num == old_block_num)
238                                 send_new_block = false;
239
240
241                 /* Get the checksum for the block number being requested. */
242                 /* Does it match our calculation?                         */
243                 
244                 receive_char();
245                 sum = rx_char;
246
247                 if (sum == chksum)
248                 {
249                         transmit_char(ACK);
250                         first_time = false;
251                 
252                         if (xfer_done == true)
253                         {
254                                 /* Send a block with a length of 0 and 128 bytes of */
255                                 /* anything along with a checksum for the block.    */
256                                 /* This tells the Coco that the file is ended.      */
257                 
258                                 tx_flag = false;
259                                 xfer_length = 0;
260                 
261                                 j = 0;
262                                 while (j <= block_size)
263                                 {
264                                         file_char[j] = 0;
265                                         ++j;
266                                 }
267                         }
268                         else
269                         {
270                                 /* go ahead and read in another 128 bytes.           */
271                                 /* If there aren't 128 bytes available pad the data  */
272                                 /* to 128 bytes. The checksum must still be correct. */
273
274                                 if (send_new_block == true)
275                                 {
276                                         count = 0;
277                                         while (count <= block_size)
278                                         {
279                                                 file_char[count] = getc(infile);
280                                                 /* The Coco can't handle linefeeds */
281                                                 if (asc_flag == ASCII)
282                                                         if (file_char[count] == '\n')
283                                                                 file_char[count] = '\r';
284                                                 xfer_length = (count + 1);
285                                                 ++count;
286                                                 if (feof(infile))
287                                                 {
288                                                         xfer_done = true;
289                                                         while (count <= block_size)
290                                                         {
291                                                                 file_char[count] = 0;
292                                                                 ++count;
293                                                                 if (asc_flag != ASCII)
294                                                                         tx_flag = false;
295                                                         }
296                                                 }
297                                         }
298                                 }
299                                 else
300                                         printf("Re-transmitting block #%d \n", block_num);
301                         }
302
303                         /* transmit whatever is in the buffer */
304
305                         transmit_char(xfer_length);
306
307                         chksum = 0;
308                         chksum = (chksum ^ xfer_length);
309                         count = 0;
310                         while (count <= block_size)
311                         {
312                                 transmit_char(file_char[count]);
313                                 chksum = (chksum ^ file_char[count]);
314                                 ++count;
315                         }
316                         transmit_char(chksum); 
317                 
318                         total_xfer = (total_xfer + xfer_length);
319                         printf("Total transmitted = %ld\r", total_xfer);
320                         old_block_num = block_num;
321                 }
322                 else
323                 {
324                         printf("checksum mismatch \n");
325                         transmit_char(NAK);
326                 }
327         }
328         printf("\n");
329 }
330
331 void xfer_abort()
332 {
333         transmit_char(NAK);
334         printf("transfer aborted by host \n");
335         exit(1);
336 }
337
338 void init_port()
339 {
340         fp = fopen(port,"a+");
341         if (!fp)
342                 printf("Error opening port\n");
343 }