/* *************************************************************************** ** ** Program reads diskette into a disk file as an image. ** Disk type is decided by the BPB on the disk. ** ** Copyright (c) 1988-1990 PFM Engineering ** Placed in the public domain. ** ** Use it, abuse it, throw it away, but leave this notice intact. ** No responsibility whatever is assumed for the suitability ** of this software. ** ** Frank Hughes ** PFM Engineering ** 5331A Williams Rd. ** Norcross GA 30093 ** ** CIS address: 74505,566 ** ** Compile: cl -Zp -AL snatch.c ** ** 28 April 1988 V1.0 FAH ** ** ** 13 July 1988 V1.1 ** Add path specification. ** ** 2 June 1990 V1.2 ** Recompile under C6.0 ** *************************************************************************** */ #include #include #include #include #include #include #include #include "snatch.h" char Version[15] = "1.2"; /* Version number */ void panic(char *data) { fprintf(stderr, "\n\nsnatch: %s\n", data); exit(-1); } /* * Print usage message. * */ void usage(void) { printf("\n\nVersion: %s\t\tPFM Engineeering\t\t060290\n", Version); printf("Usage:\n"); printf(" snatch drive: [-p file path] [-w]\n\n"); printf("\tParameters in []'s are optional.\n\tDefaults is diskette read mode into file DISKETTE.IMG\n\n"); printf("\tfile path: set filename and path\n"); printf("\t-w set diskette write mode\n\n"); exit(1); } char Signature[] = "Copyright (c) 1988-1990 PFM Engineering"; main( argc, argv) int argc; char **argv; { char *Path; FILE *f0; union REGS regs; struct SREGS sregs; unsigned char far *DiskBuf; BootSector far *SectorZero; unsigned SectorPointer, NSectors, TotalSectors; unsigned char DiskNumber; unsigned char DiskType = 0; unsigned char WriteFlag = 0; if (argc < 2) usage(); if ((DiskBuf = (unsigned char far *) calloc(122, 512)) == NULL) panic("Memory allocation error"); if ((SectorZero = (BootSector far *) calloc(1, 512)) == NULL) panic("Memory allocation error"); if ((Path = (char *) calloc(1, 80)) == NULL) panic("Memory allocation error"); strcpy(Path, "diskette.img"); /* Default file name */ for (argc--, argv++; argc > 0; argc--, argv++) { switch(**argv) { case '-': while (*++(*argv)) { /* Process all flags in this arg */ switch (**argv) { case 'p': case 'P': argv++; argc--; strcpy(Path, *argv); /* Get new filename & path */ goto nextarg; case 'w': case 'W': WriteFlag = 1; /* Set write mode */ goto nextarg; case '?': /* Help message */ case 'x': usage(); break; default: fprintf(stderr, "Unknown flag: '%c'\n", **argv); usage(); } } break; case 'a': case 'A': if ((*++(*argv)) != ':') usage(); DiskNumber = 0; break; case 'b': case 'B': if ((*++(*argv)) != ':') usage(); DiskNumber = 1; break; default: usage(); break; } nextarg: continue; } if (!WriteFlag) { /* * Read diskette */ if (DiskType == 0) { /* Set type from BPB */ regs.h.al = DiskNumber; regs.x.cx = 1; regs.x.dx = 0; sregs.ds = FP_SEG(SectorZero); regs.x.bx = FP_OFF(SectorZero); int86x( 0x25, ®s, ®s, &sregs); printf("Reading "); switch(SectorZero->MediaByte) { case 0xf0: printf("3.5'', 1.44MB diskette\n\n"); NSectors = 120; /* 24 cycles */ break; case 0xfd: printf("5.25'', 360KB diskette\n\n"); NSectors = 120; /* 6 cycles */ break; case 0xf9: switch(SectorZero->SectorsPerTrack) { case 9: printf("3.5'', 720KB diskette\n\n"); NSectors = 120; /* 12 cycles */ break; case 15: printf("5.25'', 1.2MB diskette\n\n"); NSectors = 120; /* 20 cycles */ break; default: panic("Unknown diskette type detected"); break; } break; default: panic("Unknown diskette type detected"); break; } TotalSectors = SectorZero->SectorTotal; } if ((f0 = fopen(Path, "wb")) == NULL) panic("File open error"); SectorPointer = 0; while( SectorPointer < TotalSectors ) { printf("%d%% complete\r", (int) (((float) SectorPointer / (float) TotalSectors) * 100.00)); regs.h.al = DiskNumber; regs.x.cx = NSectors; regs.x.dx = SectorPointer; sregs.ds = FP_SEG(DiskBuf); regs.x.bx = FP_OFF(DiskBuf); int86x( 0x25, ®s, ®s, &sregs); if ( regs.x.cflag & 0x01 ) { /* CY set is error */ fclose(f0); panic("Diskette read error"); } if (fwrite( DiskBuf, 512, NSectors, f0 ) != NSectors) { fclose(f0); panic("File write error"); } SectorPointer += NSectors; } printf("Complete. \n"); fclose(f0); } else { /* Write a diskette */ /* * Write a diskette. */ if ((f0 = fopen(Path, "rb")) == NULL) panic("File open error"); if (fread(SectorZero, sizeof(BootSector), 1, f0) != 1) panic("File read error"); if (DiskType == 0) { /* Set type from BPB */ printf("Writing "); switch(SectorZero->MediaByte) { case 0xf0: printf("3.5'', 1.44MB diskette\n\n"); NSectors = 120; /* 24 cycles */ break; case 0xfd: printf("5.25'', 360KB diskette\n\n"); NSectors = 120; /* 6 cycles */ break; case 0xf9: switch(SectorZero->SectorsPerTrack) { case 9: printf("3.5'', 720KB diskette\n\n"); NSectors = 120; /* 12 cycles */ break; case 15: printf("5.25'', 1.2MB diskette\n\n"); NSectors = 120; /* 20 cycles */ break; default: panic("Unknown diskette type detected"); break; } break; default: panic("Unknown diskette type detected"); break; } TotalSectors = SectorZero->SectorTotal; } if (fseek(f0, 0L, SEEK_SET)) { fclose(f0); panic("Seek failure"); } SectorPointer = 0; printf("\007WARNING!! The diskette in drive %c: will be overwritten!\n", 0x41 + DiskNumber); printf("Press ENTER to continue. Any other key aborts.\n"); if (getch() != 0x0d) panic("Operator abort"); printf("\n"); while( SectorPointer < TotalSectors ) { printf("%d%% complete\r", (int) (((float) SectorPointer / (float) TotalSectors) * 100.00)); regs.h.al = DiskNumber; regs.x.cx = NSectors; regs.x.dx = SectorPointer; sregs.ds = FP_SEG(DiskBuf); regs.x.bx = FP_OFF(DiskBuf); if (fread( DiskBuf, 512, NSectors, f0 ) != NSectors) { fclose(f0); panic("File read error"); } int86x( 0x26, ®s, ®s, &sregs); if ( regs.x.cflag & 0x01 ) { /* CY set is error */ fclose(f0); panic("Diskette write error"); } SectorPointer += NSectors; } printf("Complete. \n"); fclose(f0); } }