ldc: Small fixes (includes, less warnings etc.)
[h316.git] / pc-tools / ldc / ldc.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <fcntl.h>
5 #include <stdarg.h>
6 #include <sys/select.h>
7 #include "hw_types.h"
8 #include "hw_helpers.h"
9 #include "tape.h"
10 #include "process.h"
11 #include "split.h"
12
13 #define XON 0x11
14 #define XOFF 0x13
15 #define CHAR_START 0x81
16 // 0x93
17 #define CHAR_END1 0223
18 #define CHAR_END2 0223
19 #define CHAR_END3 0223
20 #define MAX_BLOCK_SIZE 500
21
22 //#define DEBUG
23 #define DEBUG_CHECKSUM
24 #define DEBUG_STRUCTURE
25 #define DEBUG_COMBINE
26 //#define IGNORE_CHECKSUM
27 #define HARDCORE_DEBUG
28 /********************************************************/
29 void output (char *string, int length);
30 datablock *get_block ();
31
32 /********************************************************/
33 char ends[3] = { CHAR_END1, CHAR_END2, CHAR_END3 };
34 int errflag = 0; // Global error flag
35 int tapemode = 0;
36 int inputfd;
37 int ignore = 0;
38 int dosplit = 0;
39 int splitnum = 0;
40 int silent = 0;
41 int read_pos = -5;
42 int block_pos= -5;
43 /********************************************************/
44
45
46 /********************************************************/
47 void dump_data (void *data, int count)
48 {
49 int fd = open ("dump", O_RDWR | O_CREAT | O_APPEND, 0666);
50 write (fd, "***", 3);
51 write (fd, data, count);
52 close (fd);
53 }
54
55 /********************************************************/
56 void endwarn (int ret)
57 {
58 if (ret < 1) {
59 err ("Unexpected problem in input");
60 exit (3);
61 }
62 }
63
64 /********************************************************/
65 /* Small output things */
66 void err (char *string)
67 {
68 printf ("Error: --> %s\n", string);
69 errflag++;
70 }
71
72 void msg (char *string)
73 {
74 #ifdef DEBUG
75 printf ("** %s\n", string);
76 #endif
77 }
78
79 void msgf (char *format, ...)
80 {
81 va_list ag;
82 va_start (ag, format);
83 char ms[100];
84 vsprintf (ms, format, ag);
85 msg (ms);
86 va_end (ag);
87 }
88
89 void errf (char *format, ...)
90 {
91 va_list ag;
92 va_start (ag, format);
93 char ms[100];
94 vsprintf (ms, format, ag);
95 err (ms);
96 va_end (ag);
97 }
98
99 void say (char *string)
100 {
101 if (!silent) printf ("%s\n", string);
102 }
103
104 void sayf (char *format, ...)
105 {
106 va_list ag;
107 va_start (ag, format);
108 char ms[100];
109 vsprintf (ms, format, ag);
110 say (ms);
111 va_end (ag);
112 }
113
114
115 /********************************************************/
116 /********************************************************/
117
118 /********************************************************/
119 /*Block input routines*/
120
121 unsigned char decode (unsigned char in)
122 {
123 if (in & 64)
124 switch (in) {
125 case 0174:
126 return 05;
127 break;
128 case 0374:
129 return 045;
130 break;
131 case 0175:
132 return 012;
133 break;
134 case 0375:
135 return 052;
136 break;
137 case 0176:
138 return 021;
139 break;
140 case 0376:
141 return 061;
142 break;
143 case 0177:
144 return 023;
145 break;
146 case 0377:
147 return 063;
148 break;
149 default:
150 err ("decode(): Impossible case!!!\n");
151 return 0;
152 break;
153 } else {
154 if (in & 128)
155 in |= 32;
156 return in;
157 }
158
159 return 0;
160 }
161
162 /********************************************************/
163 /********************************************************/
164
165 void combine466 (unsigned char *raw, unsigned char *data)
166 {
167 hw16 *result = (hw16 *) data;
168
169 // result->tape.low = 077;
170 unsigned char r1, r2, r3;
171
172 r1 = decode ((raw)[0]) & 017;
173 r2 = decode ((raw)[1]) & 077;
174 r3 = decode ((raw)[2]) & 077;
175
176 result->tape.high = r1;
177 result->tape.mid = r2;
178 result->tape.low = r3;
179
180 #ifdef DEBUG_COMBINE
181 msgf ("combine466 (data) : %02x %02x %02x",r1,r2,r3, 6);
182 // msgf ("combine466 (rawmem) : %s%s", bin2str (data[1], 8),
183 // bin2str (data[0], 8));
184 msgf ("combine466 (structure): %s", bin2str (result->value, 16));
185 #endif
186 }
187
188 /*********************************************************************/
189 /*********************************************************************/
190 int checksum_error (hw16 * data, int size)
191 {
192 unsigned short int checksumme = 0;
193 int c;
194 for (c = 0; c < (size - 1); c++) {
195 checksumme ^= data[c].value;
196 #ifdef DEBUG_CHECKSUM
197 msgf ("checksum_error(): Gelesen:%04x Berechnet:%04x",
198 data[c + 1].value, checksumme);
199 if (data[c + 1].value == checksumme)
200 msg ("checksum_error (): Treffer.");
201 #endif
202 }
203 #ifdef DEBUG_CHECKSUM
204 msgf ("checksum_error(): Gelesen:%04x Berechnet:%04x",
205 data[size - 1].value, checksumme);
206 #endif
207 if (data[size - 1].value != checksumme)
208 return 1;
209 return 0;
210 }
211
212 /********************************************************/
213 datablock *get_block()
214 {
215 int blk_size, round, ret, found, complete;
216 unsigned char buffer[3];
217 hw16 *blk_data;
218 unsigned char *raw_data;
219
220 if (tapemode)
221 tapestart ();
222 do {
223 read_pos+=ret=read (inputfd, buffer, 1);
224
225 #ifdef HARDCORE_DEBUG
226 msgf ("READ : (hex)%02x (bin)%s (dec)%3i (oct)%3o",
227 buffer[0], bin2str (buffer[0], 8), buffer[0], buffer[0]);
228 #endif
229 if (ret < 1) {
230 msg ("get_block(): Nichts mehr zu lesen");
231 return NULL;
232 }
233
234 if (buffer[0]==0x83){
235 datablock *result = (datablock *) malloc (sizeof (datablock));
236 result->type = BT_STOP;
237 result->data = NULL;
238 result->raw_data = NULL;
239 result->size = 0;
240 return result;
241 }
242
243 } while (*buffer != (unsigned char) CHAR_START);
244
245 block_pos=read_pos;
246 msg ("get_block(): Blockstart erkannt");
247
248 // blk_data = (hw16 *) malloc (MAX_BLOCK_SIZE * sizeof (hw16));
249 blk_data=NULL;
250 raw_data=NULL;
251 round = 0;
252 blk_size = 0;
253
254 do {
255 complete = 0;
256 ret = read (inputfd, buffer + round, 1);
257 read_pos+=ret;
258 #ifdef HARDCORE_DEBUG
259 static int lochzahl = 0;
260 char *bin = bin2str (buffer[round], 8);
261 int a;
262 for (a = 0; a < 8; a++)
263 if (bin[a] == '1')
264 lochzahl++;
265 msgf ("READ (round %i): (hex)%02x (bin)%s (dec)%3i "
266 " (oct)%3o Lochzahl:%4i",
267 round, buffer[round], bin, buffer[round], buffer[round], lochzahl);
268
269 // msgf ("READ(round %i) (hex)%02x", round, buffer[round]);
270 #endif
271 endwarn (ret);
272 round++;
273 found = 0;
274 if (buffer[round - 1] == CHAR_END1)
275 found++;
276 if (buffer[round - 1] == CHAR_END2)
277 found++;
278
279 if (found) {
280 complete++;
281 } else {
282 if (round == 3) {
283 //if (blk_size == MAX_BLOCK_SIZE) {
284 // err ("Blocküberlauf");
285 // free (blk_data);
286 // exit (4);
287 //}
288 blk_data = (hw16 *) realloc (blk_data,(blk_size+1)* sizeof (hw16));
289 raw_data = (unsigned char *) realloc (raw_data,(blk_size+1)*3);
290 memcpy(raw_data+blk_size*3,buffer,3);
291 combine466 (buffer, (unsigned char *) (blk_data + blk_size));
292 blk_size++;
293 round = 0;
294 }
295 }
296 }
297 while (complete == 0);
298
299 msgf ("get_block(): Size: %i", blk_size);
300
301 #ifdef DEBUG_STRUCTURE
302 hw16 *l1 = blk_data;
303 hw16 *l2 = blk_data + 1;
304 head0 *head = (head0 *) blk_data;
305 msgf ("get_block(): HEAD: %s", bin2str (l1->value, 16));
306 msgf ("get_block(): HEAD: %s", bin2str (l2->value, 16));
307 msgf ("get_block(): head->T: %i", head->T);
308 msgf ("get_block(): head->S: %i", head->S);
309 msgf ("get_block(): head->N: %i", head->N);
310 #endif
311
312
313 if (checksum_error (blk_data, blk_size)) {
314 errf ("get_block(): Checksum error!\nBlock start: %i (0x%x), read address %i (0x%x).",
315 block_pos,block_pos,read_pos,read_pos);
316
317
318 #ifdef CHECKSUM_DUMP
319 dump_data (buffer, 3);
320 read_pos+=read (inputfd, buffer, 3);
321 dump_data (buffer, 3);
322 #endif
323
324 if (tapemode) {
325 tapestop ();
326 sleep (15);
327 tapestart ();
328 } else {
329 if (!ignore)
330 exit (4);
331 }
332
333 } else
334 msg ("get_block(): Checksumme OK");
335
336 datablock *result = (datablock *) malloc (sizeof (datablock));
337 result->type = BT_DATA;
338 result->data = blk_data;
339 result->raw_data = raw_data;
340 result->size = blk_size;
341
342 if (tapemode)
343 tapestop ();
344 return result;
345 }
346
347 /********************************************************/
348 /**********************************************************************/
349 int main (int argc, char **args)
350 {
351 int c;
352 char *filename = NULL;
353 int blk_no = 0;
354
355 msg ("Verarbeite Kommandozeilenparameter:");
356 for (c = 1; c < argc; c++) {
357 if ((args[c][0] == '-') && (strlen (args[c]) > 1)) {
358 char action = args[c][1];
359 //msgf ("Action %c, Arg dazu:%s", action, parm);
360 switch (action) {
361 case 'I':
362 ignore=1;
363 break;
364 case 't':
365 tapemode=1;
366 break;
367 case 'S':
368 splitnum=1;
369 case 's':
370 dosplit=1;
371 break;
372 case 'l':
373 silent=1;
374 break;
375 default:
376 say ("Usage:\n");
377 sayf ("%s [-t] [-S] [-n] [-I] [filename]", args[0]);
378 sayf ("");
379 sayf (" -t Tape mode. Uses tty device and stops on error.");
380 sayf (" -S Split library tape into separate numbered files");
381 sayf (" -s same as -S but no numbering");
382 sayf (" -I Ignore errors");
383 sayf (" -l be silent");
384 sayf ("");
385 exit (1);
386 break;
387 }
388 } else {
389 filename = args[c];
390 }
391 }
392
393 //Use file?
394 if (filename != NULL) {
395 msgf ("Using file:%s", filename);
396 inputfd = open (filename, O_RDWR);
397 if (inputfd < 0) {
398 perror ("File");
399 err ("Sorry, exiting.");
400 exit (3);
401 }
402 } else {
403 inputfd = 0;
404 if (tapemode) {
405 err ("Use of console as tape device not allowed! Please specify a suitable device!");
406 exit(1);
407 }
408 }
409
410 if (tapemode) {
411 msg ("Tapemode aktiviert.");
412 if (!isatty (inputfd)) {
413 err ("Input file doesn't seem to be a tty.\nNot using tape mode on files!\nQuit.");
414 exit (1);
415 }
416 tapeinit (inputfd);
417 }
418 datablock *akt_block;
419
420 /* Initialize read position */
421 read_pos=0;
422
423 while (1) {
424 msg ("********************************************************");
425 msgf ("Block no. %5i", blk_no++);
426
427 akt_block = get_block ();
428 if (akt_block == NULL) {
429 msg ("Ende der Verarbeitung.");
430
431 msgf ("Errflag:%i", errflag);
432 if (errflag)
433 sayf ("** Es gab Fehler.");
434 exit (0);
435 }
436 // Verarbeitung hier
437
438 process_block (akt_block);
439 if (dosplit) split(akt_block);
440
441 free (akt_block->data);
442 free (akt_block->raw_data);
443 free (akt_block);
444 } // Endlosschleife
445 } //main();
446
447 // end.