1 /*
2 NIBSCAN - part of the NIBTOOLS package for 1541/1571 disk image nibbling
3 by Peter Rittwage <peter(at)rittwage(dot)com>
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10 #include <ctype.h>
11
12 #include "mnibarch.h"
13 #include "gcr.h"
14 #include "nibtools.h"
15 #include "prot.h"
16 #include "md5.h"
17 #include "lz.h"
18
19 int _dowildcard = 1;
20
21 char bitrate_range[4] = { 43 * 2, 31 * 2, 25 * 2, 18 * 2 };
22
23 int load_image(char *filename, BYTE *track_buffer, BYTE *track_density, size_t *track_length);
24 int compare_disks(void);
25 int scandisk(void);
26 int raw_track_info(BYTE *gcrdata, size_t length);
27 int dump_headers(BYTE * gcrdata, size_t length);
28 size_t check_fat(int track);
29 size_t check_rapidlok(int track);
30
31 BYTE compressed_buffer[(MAX_HALFTRACKS_1541 + 2) * NIB_TRACK_LENGTH];
32 BYTE file_buffer[(MAX_HALFTRACKS_1541 + 2) * NIB_TRACK_LENGTH];
33 BYTE track_buffer[(MAX_HALFTRACKS_1541 + 2) * NIB_TRACK_LENGTH];
34 BYTE track_buffer2[(MAX_HALFTRACKS_1541 + 2) * NIB_TRACK_LENGTH];
35 size_t track_length[MAX_HALFTRACKS_1541 + 2];
36 size_t track_length2[MAX_HALFTRACKS_1541 + 2];
37 BYTE track_density[MAX_HALFTRACKS_1541 + 2];
38 BYTE track_density2[MAX_HALFTRACKS_1541 + 2];
39 BYTE track_alignment[MAX_HALFTRACKS_1541 + 2];
40 BYTE track_alignment2[MAX_HALFTRACKS_1541 + 2];
41
42 size_t fat_tracks[MAX_HALFTRACKS_1541 + 2];
43 size_t rapidlok_tracks[MAX_HALFTRACKS_1541 + 2];
44 size_t badgcr_tracks[MAX_HALFTRACKS_1541 + 2];
45
46 int start_track, end_track, track_inc;
47 int imagetype, mode;
48 int align, force_align;
49 int file_buffer_size;
50 int fix_gcr;
51 int reduce_sync;
52 int reduce_badgcr;
53 int reduce_gap;
54 int waitkey = 0;
55 int gap_match_length;
56 int cap_relax;
57 int verbose;
58 int rpm_real;
59 int auto_capacity_adjust;
60 int skew;
61 int align_disk;
62 int ihs;
63 int unformat_passes;
64 int capacity_margin;
65 int align_delay;
66 int cap_min_ignore;
67 int increase_sync = 0;
68 int presync = 0;
69 BYTE fillbyte = 0x55;
70 BYTE drive = 8;
71 char * cbm_adapter = "";
72 int use_floppycode_srq = 0;
73 int extra_capacity_margin=5;
74 int sync_align_buffer=0;
75 int fattrack=0;
76 int track_match=0;
77 int old_g64=0;
78
79 unsigned char md5_hash_result[16];
80 unsigned char md5_dir_hash_result[16];
81 unsigned char md5_hash_result2[16];
82 unsigned char md5_dir_hash_result2[16];
83 int crc, crc_dir, crc2, crc2_dir;
84
85 int ARCH_MAINDECL
main(int argc,char * argv[])86 main(int argc, char *argv[])
87 {
88 char file1[256];
89 char file2[256];
90 int i;
91
92 start_track = 1 * 2;
93 end_track = 42 * 2;
94 track_inc = 2;
95 align = ALIGN_NONE;
96 force_align = ALIGN_NONE;
97 fix_gcr = 0;
98 gap_match_length = 7;
99 cap_relax = 0;
100 mode = 0;
101 reduce_sync = 4;
102 reduce_badgcr = 0;
103 reduce_gap = 0;
104 rpm_real = 296;
105 verbose = 1;
106 cap_min_ignore = 0;
107
108 fprintf(stdout,
109 "\nnibscan - Commodore disk image scanner / comparator\n"
110 AUTHOR "Revision %d - " VERSION "\n\n", SVN);
111
112 /* we can do nothing with no switches */
113 if (argc < 2)
114 usage();
115
116 /* clear heap buffers */
117 memset(compressed_buffer, 0x00, sizeof(compressed_buffer));
118 memset(file_buffer, 0x00, sizeof(file_buffer));
119 memset(track_buffer, 0x00, sizeof(track_buffer));
120 memset(track_buffer2, 0x00, sizeof(track_buffer2));
121
122 /* default is to reduce sync */
123 memset(reduce_map, REDUCE_SYNC, MAX_TRACKS_1541+2);
124
125 while (--argc && (*(++argv)[0] == '-'))
126 parseargs(argv);
127
128 if (argc < 0) usage();
129 strcpy(file1, argv[0]);
130
131 if (argc > 1)
132 {
133 mode = 1; //compare
134 strcpy(file2, argv[1]);
135 }
136 printf("\n");
137
138 if (mode == 1) // compare images
139 {
140 if(!(load_image(file1, track_buffer, track_density, track_length))) exit(0);
141 if(!(load_image(file2, track_buffer2, track_density2, track_length2))) exit(0);
142
143 compare_disks();
144
145 /* disk 1 */
146 printf("\n1: %s\n", file1);
147
148 crc_dir = crc_dir_track(track_buffer, track_length);
149 printf("BAM/DIR CRC:\t\t\t0x%X\n", crc_dir);
150 crc = crc_all_tracks(track_buffer, track_length);
151 printf("Full CRC:\t\t\t0x%X\n", crc);
152
153 memset(md5_dir_hash_result, 0 , sizeof(md5_dir_hash_result));
154 md5_dir_track(track_buffer, track_length, md5_dir_hash_result);
155 printf("BAM/DIR MD5:\t\t\t0x");
156 for (i = 0; i < 16; i++)
157 printf ("%02x", md5_dir_hash_result[i]);
158 printf("\n");
159
160 memset(md5_hash_result, 0 , sizeof(md5_hash_result));
161 md5_all_tracks(track_buffer, track_length, md5_hash_result);
162 printf("Full MD5:\t\t\t0x");
163 for (i = 0; i < 16; i++)
164 printf ("%02x", md5_hash_result[i]);
165 printf("\n");
166
167 /* disk 2 */
168 printf("\n2: %s\n", file2);
169 crc2_dir = crc_dir_track(track_buffer2, track_length2);
170 printf("BAM/DIR CRC:\t\t\t0x%X\n", crc2_dir);
171 crc2 = crc_all_tracks(track_buffer2, track_length2);
172 printf("Full CRC:\t\t\t0x%X\n", crc2);
173
174 memset(md5_dir_hash_result2, 0 , sizeof(md5_dir_hash_result2));
175 md5_dir_track(track_buffer2, track_length2, md5_dir_hash_result2);
176 printf("BAM/DIR MD5:\t\t\t0x");
177 for (i = 0; i < 16; i++)
178 printf ("%02x", md5_dir_hash_result2[i]);
179 printf("\n");
180
181 memset(md5_hash_result2, 0 , sizeof(md5_hash_result2));
182 md5_all_tracks(track_buffer2, track_length2, md5_hash_result2);
183 printf("Full MD5:\t\t\t0x");
184 for (i = 0; i < 16; i++)
185 printf ("%02x", md5_hash_result2[i]);
186 printf("\n\n");
187
188 /* compare summary */
189 if(crc_dir == crc2_dir)
190 printf("BAM/DIR CRC matches.\n");
191 else
192 printf("BAM/DIR CRC does not match.\n");
193
194 if( memcmp(md5_dir_hash_result, md5_dir_hash_result2, 16 ) == 0 )
195 printf("BAM/DIR MD5 matches.\n");
196 else
197 printf("BAM/DIR MD5 does not match.\n");
198
199 if(crc == crc2)
200 printf("All decodable sectors have CRC matches.\n");
201 else
202 printf("All decodable sectors do not have CRC matches.\n");
203
204 if( memcmp(md5_hash_result, md5_hash_result2, 16 ) == 0 )
205 printf("All decodable sectors have MD5 matches.\n");
206 else
207 printf("All decodable sectors do not have MD5 matches.\n");
208 }
209 else // just scan for errors, etc.
210 {
211 if(!load_image(file1, track_buffer, track_density, track_length)) exit(0);
212
213 scandisk();
214
215 printf("\n%s\n", file1);
216
217 crc = crc_dir_track(track_buffer, track_length);
218 printf("BAM/DIR CRC:\t0x%X\n", crc);
219 crc = crc_all_tracks(track_buffer, track_length);
220 printf("Full CRC:\t0x%X\n", crc);
221
222 memset(md5_hash_result, 0 , sizeof(md5_hash_result));
223 md5_dir_track(track_buffer, track_length, md5_hash_result);
224 printf("BAM/DIR MD5:\t0x");
225 for (i = 0; i < 16; i++)
226 printf ("%02x", md5_hash_result[i]);
227 printf("\n");
228
229 memset(md5_hash_result, 0 , sizeof(md5_hash_result));
230 md5_all_tracks(track_buffer, track_length, md5_hash_result);
231 printf("Full MD5:\t0x");
232 for (i = 0; i < 16; i++)
233 printf ("%02x", md5_hash_result[i]);
234 printf("\n");
235 }
236
237 exit(0);
238 }
239
load_image(char * filename,BYTE * track_buffer,BYTE * track_density,size_t * track_length)240 int load_image(char *filename, BYTE *track_buffer, BYTE *track_density, size_t *track_length)
241 {
242 if (compare_extension(filename, "D64"))
243 {
244 if(!(read_d64(filename, track_buffer, track_density, track_length))) return 0;
245 }
246 else if (compare_extension(filename, "G64"))
247 {
248 if(!(read_g64(filename, track_buffer, track_density, track_length))) return 0;
249 if(sync_align_buffer) sync_tracks(track_buffer, track_density, track_length, track_alignment);
250 }
251 else if (compare_extension(filename, "NBZ"))
252 {
253 printf("Uncompressing NBZ...\n");
254 if(!(file_buffer_size = load_file(filename, compressed_buffer))) return 0;
255 if(!(file_buffer_size = LZ_Uncompress(compressed_buffer, file_buffer, file_buffer_size))) return 0;
256 if(!(read_nib(file_buffer, file_buffer_size, track_buffer, track_density, track_length))) return 0;
257 align_tracks(track_buffer, track_density, track_length, track_alignment);
258 search_fat_tracks(track_buffer, track_density, track_length);
259 }
260 else if (compare_extension(filename, "NIB"))
261 {
262 if(!(file_buffer_size = load_file(filename, file_buffer))) return 0;
263 if(!(read_nib(file_buffer, file_buffer_size, track_buffer, track_density, track_length))) return 0;
264 align_tracks(track_buffer, track_density, track_length, track_alignment);
265 search_fat_tracks(track_buffer, track_density, track_length);
266 }
267 else if (compare_extension(filename, "NB2"))
268 {
269 if(!(read_nb2(filename, track_buffer, track_density, track_length))) return 0;
270 align_tracks(track_buffer, track_density, track_length, track_alignment);
271 search_fat_tracks(track_buffer, track_density, track_length);
272 }
273 else
274 {
275 printf("Unknown image type = %s!\n", filename);
276 return 0;
277 }
278 return 1;
279 }
280
281 int
compare_disks(void)282 compare_disks(void)
283 {
284 int track;
285 size_t numtracks = 0;
286 size_t numsecs = 0;
287 size_t gcr_match = 0;
288 size_t sec_match = 0;
289 size_t dens_mismatch = 0;
290 size_t gcr_total = 0;
291 size_t sec_total = 0;
292 size_t trk_total = 0;
293 size_t errors_d1 = 0, errors_d2 = 0;
294 size_t gcr_percentage;
295 char gcr_mismatches[256];
296 char sec_mismatches[256];
297 char gcr_matches[256];
298 char sec_matches[256];
299 char dens_mismatches[256];
300 char tmpstr[16];
301 char errorstring[0x1000];
302 BYTE id[3], id2[3], cid[3], cid2[3];
303
304 gcr_mismatches[0] = '\0';
305 sec_mismatches[0] = '\0';
306 gcr_matches[0] = '\0';
307 sec_matches[0] = '\0';
308 dens_mismatches[0] = '\0';
309
310 /* ignore halftracks in compare */
311 track_inc = 2;
312
313 // extract disk id's from track 18
314 memset(id, 0, 3);
315 extract_id(track_buffer + (36 * NIB_TRACK_LENGTH), id);
316 memset(id2, 0, 3);
317 extract_id(track_buffer2 + (36 * NIB_TRACK_LENGTH), id2);
318
319 memset(cid, 0, 3);
320 extract_cosmetic_id(track_buffer + (36 * NIB_TRACK_LENGTH), cid);
321 memset(cid2, 0, 3);
322 extract_cosmetic_id(track_buffer2 + (36 * NIB_TRACK_LENGTH), cid2);
323
324 if(waitkey) getchar();
325 printf("\nComparing...\n");
326
327 for (track = start_track; track <= end_track; track ++)
328 {
329 if(!check_formatted(track_buffer + (track * NIB_TRACK_LENGTH), track_length[track]))
330 {
331 track_length[track] = 0;
332 //printf("1 - UNFORMATTED!\n");
333 continue;
334 }
335
336 if(!check_formatted(track_buffer2 + (track * NIB_TRACK_LENGTH), track_length2[track]))
337 {
338 track_length2[track] = 0;
339 //printf("2 - UNFORMATTED!\n");
340 continue;
341 }
342
343 printf("%4.1f, Disk 1: (%d) %d\n",
344 (float)track/2, track_density[track]&3, track_length[track]);
345
346 printf("%4.1f, Disk 2: (%d) %d\n",
347 (float)track/2, track_density2[track]&3, track_length2[track]);
348
349 numtracks++;
350
351 // check for gcr match (unlikely)
352 gcr_match =
353 compare_tracks(
354 track_buffer + (track * NIB_TRACK_LENGTH),
355 track_buffer2 + (track * NIB_TRACK_LENGTH),
356 track_length[track],
357 track_length2[track],
358 0,
359 errorstring);
360
361 printf("%s", errorstring);
362
363 if(gcr_match)
364 {
365 gcr_percentage = (gcr_match*100)/track_length[track];
366
367 if (gcr_percentage >= 98)
368 {
369 gcr_total++;
370 printf("\n[*>%d%% GCR MATCH*]\n", (gcr_match*100)/track_length[track]);
371 sprintf(tmpstr, "%d,", track/2);
372 strcat(gcr_matches, tmpstr);
373 }
374 else
375 {
376 printf("\n[*>%d%% GCR MATCH*]\n", (gcr_match*100)/track_length[track]);
377 sprintf(tmpstr, "%d,", track/2);
378 strcat(gcr_mismatches, tmpstr);
379 }
380 }
381
382 if(track/2 <= 35)
383 {
384 errors_d1 += check_errors(track_buffer + (NIB_TRACK_LENGTH * track), track_length[track], track, id, errorstring);
385 errors_d2 += check_errors(track_buffer2 + (NIB_TRACK_LENGTH * track), track_length2[track], track, id2, errorstring);
386 }
387
388 /* check for DOS sector matches */
389 if(track/2 <= 35)
390 {
391 sec_match = compare_sectors(
392 track_buffer + (track * NIB_TRACK_LENGTH),
393 track_buffer2 + (track * NIB_TRACK_LENGTH),
394 track_length[track],
395 track_length2[track],
396 id,
397 id2,
398 track,
399 errorstring
400 );
401
402 printf("%s", errorstring);
403
404 sec_total += sec_match;
405 numsecs += sector_map[track/2];
406
407 if (sec_match == sector_map[track/2])
408 {
409 trk_total++;
410 printf("[*Data MATCH*]\n");
411 sprintf(tmpstr, "%d,", track / 2);
412 strcat(sec_matches, tmpstr);
413 }
414 else
415 {
416 printf("[*Data MISmatch*]\n");
417 sprintf(tmpstr, "%d,", track / 2);
418 strcat(sec_mismatches, tmpstr);
419 }
420 }
421
422 if(track_density[track] != track_density2[track])
423 {
424 printf("[Densities do not match: %d != %d]\n", track_density[track], track_density2[track]);
425 dens_mismatch++;
426 sprintf(tmpstr, "%d,", track / 2);
427 strcat(dens_mismatches, tmpstr);
428 }
429 printf("\n");
430
431 if((!sec_match) || (track_density[track] != track_density2[track]))
432 if( waitkey) getchar();
433 }
434
435 printf("\n---------------------------------------------------------------------\n");
436 printf("%d/%d tracks had at least 98%% GCR match\n", gcr_total, numtracks);
437 //printf("Matches (%s)\n", gcr_matches);
438 //printf("Mismatches (%s)\n", gcr_mismatches);
439 //printf("\n");
440 printf("%d/%d of likely formatted tracks matched all sector data\n", trk_total, numtracks);
441 //printf("Matches (%s)\n", sec_matches);
442 //printf("Mismatches (%s)\n", sec_mismatches);
443 //printf("\n");
444 printf("%d/%d total sectors (or errors) matched (%d mismatched)\n", sec_total, numsecs, numsecs-sec_total);
445 printf("CBM DOS errors (d1/%d - d2/%d)\n",errors_d1, errors_d2);
446 printf("%d tracks had mismatched densities (%s)\n", dens_mismatch, dens_mismatches);
447
448 if(!(id[0]==id2[0] && id[1]==id2[1]))
449 printf("\nFormat ID's do not match!:\t(%s != %s)", id, id2);
450 else
451 printf("\nFormat ID's match:\t\t(%s = %s)", id, id2);
452
453 if(!(cid[0]==cid2[0] && cid[1]==cid2[1]))
454 printf("\nCosmetic ID's do not match:\t(%s != %s)\n", cid, cid2);
455 else
456 printf("\nCosmetic ID's match:\t\t(%s = %s)\n", cid, cid2);
457
458 printf("---------------------------------------------------------------------\n");
459
460 return 1;
461 }
462
463 int
scandisk(void)464 scandisk(void)
465 {
466 BYTE id[3], cosmetic_id[3];
467 int track = 0;
468 int totalfat = 0;
469 int totalrl = 0;
470 int added_sync;
471 size_t totalgcr = 0;
472 int total_wrong_density = 0;
473 size_t empty = 0, temp_empty = 0;
474 size_t errors = 0, temp_errors = 0;
475 int defdensity;
476 char errorstring[0x1000];
477 char testfilename[16];
478 FILE *trkout;
479
480 // clear buffers
481 memset(badgcr_tracks, 0, sizeof(badgcr_tracks));
482 memset(fat_tracks, 0, sizeof(fat_tracks));
483 memset(rapidlok_tracks, 0, sizeof(rapidlok_tracks));
484 errorstring[0] = '\0';
485
486 printf("\nScanning...\n");
487
488 // extract disk id from track 18
489 memset(id, 0, 3);
490 extract_id(track_buffer + (36 * NIB_TRACK_LENGTH), id);
491 printf("\ndisk id: %s\n", id);
492
493 // collect and print "cosmetic" disk id for comparison
494 memset(cosmetic_id, 0, 3);
495 extract_cosmetic_id(track_buffer + (36 * NIB_TRACK_LENGTH), cosmetic_id);
496 printf("cosmetic disk id: %s\n", cosmetic_id);
497
498 if(waitkey) getchar();
499
500 // check each track for various things
501 for (track = start_track; track <= end_track; track ++)
502 {
503 if(!check_formatted(track_buffer + (track * NIB_TRACK_LENGTH), track_length[track]))
504 //printf("UNFORMATTED");
505 continue;
506 else
507 printf("%4.1f: %d",(float) track/2, track_length[track]);
508
509 if (track_length[track] > 0)
510 {
511 track_density[track] = check_sync_flags(track_buffer + (track * NIB_TRACK_LENGTH),
512 track_density[track]&3, track_length[track]);
513
514 printf("(%d", track_density[track]&3);
515
516 if (track_density[track] & BM_NO_SYNC)
517 printf(":NOSYNC");
518 else if (track_density[track] & BM_FF_TRACK)
519 printf(":KILLER");
520
521 // establish default density and warn
522 defdensity = speed_map[track/2];
523
524 if ((track_density[track] & 3) != defdensity)
525 {
526 printf("!=%d?) ", defdensity);
527 if(track < 36*2) total_wrong_density++;
528 if(waitkey) getchar();
529 }
530 else
531 printf(") ");
532
533 if(increase_sync)
534 {
535 added_sync = lengthen_sync(track_buffer + (NIB_TRACK_LENGTH * track),
536 track_length[track], NIB_TRACK_LENGTH);
537
538 printf("[sync:%d] ", added_sync);
539 track_length[track] += added_sync;
540 }
541
542 // detect bad GCR '000' bits
543 //if (fix_gcr)
544 {
545 badgcr_tracks[track] =
546 check_bad_gcr(track_buffer + (NIB_TRACK_LENGTH * track), track_length[track]);
547
548 if (badgcr_tracks[track])
549 {
550 //printf("weak:%d ", badgcr_tracks[track]);
551 totalgcr += badgcr_tracks[track];
552 }
553 }
554
555 /* check for rapidlok track
556 rapidlok_tracks[track] = check_rapidlok(track);
557
558 if (rapidlok_tracks[track]) totalrl++;
559 if ((totalrl) && (track == 72))
560 {
561 printf("RAPIDLOK KEYTRACK ");
562 rapidlok_tracks[track] = 1;
563 }
564 */
565
566 /* check for FAT track */
567 if (track < end_track - track_inc)
568 {
569 fat_tracks[track] = check_fat(track);
570 if (fat_tracks[track]) totalfat++;
571 }
572
573 /* check for regular disk errors
574 "second half" of fat track will always have header
575 errors since it's encoded for the wrong track number.
576 rapidlok tracks are not standard gcr
577 tracks above 35 are always CBM errors
578 */
579 if(track/2 <= 35)
580 temp_errors = check_errors(track_buffer + (NIB_TRACK_LENGTH * track), track_length[track], track, id, errorstring);
581 else /* everything is a CBM error above track 35 */
582 temp_errors = 0;
583
584 if (temp_errors)
585 {
586 errors += temp_errors;
587 printf("%s", errorstring);
588 if(waitkey) getchar();
589 }
590
591 temp_empty = check_empty(track_buffer + (NIB_TRACK_LENGTH * track), track_length[track], track, id, errorstring);
592 if (temp_empty)
593 {
594 empty += temp_empty;
595 if(verbose>1) printf(" %s", errorstring);
596 }
597
598 if (verbose>1)
599 {
600 dump_headers(track_buffer + (NIB_TRACK_LENGTH * track), track_length[track]);
601 raw_track_info(track_buffer + (NIB_TRACK_LENGTH * track), track_length[track]);
602 }
603 }
604 printf("\n");
605
606 // process and dump to disk for manual compare
607 //track_length[track] = compress_halftrack(track, track_buffer + (track * NIB_TRACK_LENGTH), track_density[track], track_length[track]);
608
609 sprintf(testfilename, "raw/tr%.1fd%d", (float) track/2, (track_density[track] & 3));
610 if(NULL != (trkout = fopen(testfilename, "w")))
611 {
612 fwrite(track_buffer + (track * NIB_TRACK_LENGTH), track_length[track], 1, trkout);
613 fclose(trkout);
614 }
615 }
616 printf("\n---------------------------------------------------------------------\n");
617 printf("%d unrecognized sectors (CBM disk errors) detected\n", errors);
618 printf("%d known empty sectors detected\n", empty);
619 printf("%d bad GCR bytes detected\n", totalgcr);
620 printf("%d fat tracks detected\n", totalfat);
621 printf("%d rapidlok tracks detected\n", totalrl);
622 printf("%d tracks with non-standard density\n", total_wrong_density);
623 return 1;
624 }
625
626 int
dump_headers(BYTE * gcrdata,size_t length)627 dump_headers(BYTE * gcrdata, size_t length)
628 {
629 BYTE header[10];
630 BYTE *gcr_ptr, *gcr_end;
631
632 gcr_ptr = gcrdata;
633 gcr_end = gcrdata + length;
634
635 do
636 {
637 if (!find_sync(&gcr_ptr, gcr_end))
638 return 0;
639
640 convert_4bytes_from_GCR(gcr_ptr, header);
641 convert_4bytes_from_GCR(gcr_ptr + 5, header + 4);
642
643 if(header[0] == 0x08) // only parse headers
644 printf("\n%.2x %.2x %.2x %.2x = typ:%.2x -- blh:%.2x -- trk:%.2x -- sec:%.2x -- id:%c%c",
645 *gcr_ptr, *(gcr_ptr+1), *(gcr_ptr+2), *(gcr_ptr+3), header[0], header[1], header[3], header[2], header[5], header[4]);
646 else // data block should follow
647 printf("\n%.2x %.2x %.2x %.2x = typ:%.2x",
648 *gcr_ptr, *(gcr_ptr+1), *(gcr_ptr+2), *(gcr_ptr+3), header[0]);
649
650 } while (gcr_ptr < (gcr_end - 10));
651
652 printf("\n");
653
654 return 1;
655 }
656
657
658 int
raw_track_info(BYTE * gcrdata,size_t length)659 raw_track_info(BYTE * gcrdata, size_t length)
660 {
661 size_t sync_cnt = 0;
662 size_t sync_len[NIB_TRACK_LENGTH];
663 /*
664 int gap_cnt = 0;
665 int gap_len[NIB_TRACK_LENGTH];
666 */
667 size_t bad_cnt = 0;
668 size_t bad_len[NIB_TRACK_LENGTH];
669 size_t i, locked;
670
671 memset(sync_len, 0, sizeof(sync_len));
672 /* memset(gap_len, 0, sizeof(gap_len)); */
673 memset(bad_len, 0, sizeof(bad_len));
674
675 /* count syncs/lengths */
676 for (locked = 0, i = 0; i < length - 1; i++)
677 {
678 if (locked)
679 {
680 if (gcrdata[i] == 0xff)
681 sync_len[sync_cnt]++;
682 else
683 locked = 0;
684 }
685 //else if (gcrdata[i] == 0xff) /* not full sync, only last 8 bits */
686 else if(((gcrdata[i] & 0x03) == 0x03) && (gcrdata[i+1] == 0xff))
687 {
688 locked = 1;
689 sync_cnt++;
690 sync_len[sync_cnt] = 1;
691 }
692 }
693
694 printf("\nSYNCS:%d (", sync_cnt);
695 for (i = 1; i <= sync_cnt; i++)
696 printf("%d-", sync_len[i]);
697 printf(")");
698
699 /* count gaps/lengths - this code is innacurate, since gaps are of course not always 0x55 - they rarely are */
700 /*
701 for (locked = 0, i = 0; i < length - 1; i++)
702 {
703 if (locked)
704 {
705 if (gcrdata[i] == 0x55)
706 gap_len[gap_cnt]++;
707 else
708 locked = 0;
709 }
710 else if ((gcrdata[i] == 0x55) && (gcrdata[i + 1] == 0x55))
711 {
712 locked = 1;
713 gap_cnt++;
714 gap_len[gap_cnt] = 2;
715 }
716 }
717
718 printf("\nGAPS :%d (", gap_cnt);
719 for (i = 1; i <= gap_cnt; i++)
720 printf("%d-", gap_len[i]);
721 printf(")");
722 */
723
724 /* count bad gcr lengths */
725 for (locked = 0, i = 0; i < length - 1; i++)
726 {
727 if (locked)
728 {
729 if (is_bad_gcr(gcrdata, length, i))
730 bad_len[bad_cnt]++;
731 else
732 locked = 0;
733 }
734 else if (is_bad_gcr(gcrdata, length, i))
735 {
736 locked = 1;
737 bad_cnt++;
738 bad_len[bad_cnt] = 1;
739 }
740 }
741
742 printf("\nBADGCR:%d (", bad_cnt);
743 for (i = 1; i <= bad_cnt; i++)
744 printf("%d-", bad_len[i]);
745 printf(")");
746
747 return 1;
748 }
749
check_fat(int track)750 size_t check_fat(int track)
751 {
752 size_t diff = 0;
753 char errorstring[0x1000];
754
755 if (track_length[track] > 0 && track_length[track+2] > 0 && track_length[track] != 8192 && track_length[track+2] != 8192)
756 {
757 diff = compare_tracks(
758 track_buffer + (track * NIB_TRACK_LENGTH),
759 track_buffer + ((track+2) * NIB_TRACK_LENGTH),
760 track_length[track],
761 track_length[track+2], 1, errorstring);
762
763 if(verbose>1) printf("%s",errorstring);
764
765 if (diff<=10)
766 {
767 printf("*FAT diff=%d*",track/2,(int)diff);
768 return 1;
769 }
770 else if (diff<=35)
771 {
772 printf("*Possible FAT diff=%d*",track/2,(int)diff);
773 return 1;
774 }
775 else
776 if(verbose>1) printf("diff=%d",(int)diff);
777 }
778 return 0;
779 }
780
781 /*
782 tries to detect and fixup rapidlok track, as the gcr routines
783 don't assemble them quite right.
784 this is innaccurate!
785 */
786
check_rapidlok(int track)787 size_t check_rapidlok(int track)
788 {
789 size_t i;
790 size_t end_key = 0;
791 size_t end_sync = 0;
792 size_t synclen = 0;
793 size_t keylen = 0; // extra sector with # of 0x7b
794 size_t tlength = track_length[track];
795 BYTE *gcrdata = track_buffer + (track * NIB_TRACK_LENGTH);
796
797 // extra sector is at the end.
798 // count the extra-sector (key) bytes.
799 for (i = 0; i < 200; i++)
800 {
801 if (gcrdata[tlength - i] == 0x7b)
802 {
803 keylen++;
804 if (end_key)
805 end_key = tlength - i; // move marked end of key bytes
806 }
807 else if (keylen)
808 break;
809 }
810
811 if (gcrdata[tlength - i] != 0xff)
812 {
813 keylen++;
814 end_key++;
815 }
816
817 // only rapidlok tracks contain lots of these at start
818 if (keylen < 0x8)
819 return (0);
820
821 for (i = end_key + 1; i < end_key + 0x100; i++)
822 {
823 if (gcrdata[i] == 0xff)
824 {
825 synclen++;
826 end_sync = i + 1; // mark end of sync
827 }
828 else if (synclen)
829 break;
830 }
831
832 printf("RAPIDLOK! ");
833 printf("key:%d, sync:%d...", keylen, synclen);
834
835 #if 0
836 // recreate key sector
837 memset(extra_sector, 0xff, 0x14);
838 memset(extra_sector + 0x14, 0x7b, keylen);
839
840 // create initial sync, then copy all sector data
841 // if directory track no fancy stuff
842 if(halftrack != 0x24)
843 {
844 memset(gcrdata, 0xff, 0x29);
845 memcpy(gcrdata + 0x29, gcrdata + end_sync, length - end_sync);
846 memcpy(gcrdata + 0x29 + (length - end_sync), extra_sector,
847 keylen + 0x14);
848 }
849 else
850 {
851 memcpy(gcrdata, gcrdata + end_key, length - end_key);
852 memcpy(gcrdata + (length - end_key), extra_sector, keylen + 0x14);
853 }
854 #endif // 0
855
856 return keylen;
857 }
858
859 void
usage(void)860 usage(void)
861 {
862 fprintf(stderr, "usage: nibscan [options] <filename1> [filename2]\n\n");
863 switchusage();
864 exit(1);
865 }
866
867