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