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