/* ** dcmtoatr.c -- written by Chad Wagner ** ** I just wanted to throw in some personal comments, I wanted to thank ** Preston Crow, for his work on portability issues, as well as some of ** the ideas he put into this program, Bob Puff, for his hard work on ** The Disk Communicator, an excellent means for transferring disk images, ** and I feel it is the de facto standard, and should remain as such, and ** Jason Duerstock, for writing DCMTODSK and his documents on the DCM ** format, which did help me resolve some of the things I wasn't aware of. ** I am sure there is a few others. Unfortunately I only got one response ** from Bob Puff, he was attempting to help, but I believe he is very busy ** person, and just didn't have the time. ** ** Revision History: ** 31 May 95 cmwagner@gate.net ** 1 Jun 95 cmwagner@gate.net ** added in some portability macros from dcm.c ** added in read_atari16() function from dcm.c ** wrote write_atari16() function ** did a general clean-up of the code ** 1 Jun 95 crow@cs.dartmouth.edu ** did a clean-up of the code, hopefully resolving any ** portability issues ** 2 Jun 95 cmwagner@gate.net and crow@cs.dartmouth.edu ** Allow for multi-file DCM files, after they've been ** combined into a single file ** 5 Jun 95 cmwagner@gate.net ** Fixed decoding routines to handle double density diskettes ** 26 Jun 95 cmwagner@gate.net ** Added in support for creating DCMTOXFD, default compile is ** for DCMTOATR ** 3 Sep 95 cmwagner@gate.net ** Added in -x switch, which creates an XFD image, instead of the ** default ATR image. ** added in soffset() routine, changed around the SOFFSET define, ** so that xfd images could be created, without compiling a ** different version. ** 26 Jun 95 modification is no longer relevant because of this ** modification. ** wrote some more comments, about what certain functions are doing, ** when they were created, and who wrote them. ** 28 Sep 95 lovegrov@student.umass.edu ** Fixed bug in soffset() function, apparently sector 4 would return ** an offset of 16 for ATR images or 0 for XFD images, which is not ** correct. */ /* Include files */ #include #include /* prototypes */ void decode_C1(void); void decode_C3(void); void decode_C4(void); void decode_C6(void); void decode_C7(void); void decode_FA(void); int read_atari16(FILE *); void write_atari16(FILE *,int); int read_offset(FILE *); void read_sector(FILE *); void write_sector(FILE *); long soffset(void); /* ** Portability macros ** 1 Jun 95 crow@cs.dartmouth.edu (Preston Crow) */ #if defined(__MSDOS) || defined(__MSDOS__) || defined(_MSDOS) || defined(_MSDOS_) #define MSDOS /* icky, icky, icky! */ #endif #ifndef SEEK_SET #define SEEK_SET 0 /* May be missing from stdio.h */ #endif /* version of this program, as seen in usage message */ #define VERSION "1.4" /* Global variables */ FILE *fin,*fout; unsigned int secsize; unsigned short cursec=0,maxsec=0; unsigned char createdisk=0,working=0,last=0,density,buf[256],atr=16; int doprint=1; /* True for diagnostic output */ /* ** main() */ int main(int argc,char **argv) { unsigned char archivetype; /* Block type for first block */ unsigned char blocktype; /* Current block type */ unsigned char tmp; /* Temporary for read without clobber on eof */ unsigned char imgin[256],imgout[256]; /* file names */ unsigned char done=0; /* completion flag */ char *self; /* program name from argv[0] */ #ifdef MSDOS if ((self = strrchr(argv[0],'\\')) == NULL) #else if ((self = strrchr(argv[0],'/')) == NULL) #endif { self = argv[0]; } else self++; /* Skip the slash */ --argc;++argv; /* Don't look at the filename anymore */ /* Process switches */ if (argc) while (*argv[0]=='-') { int nomore=0; ++argv[0]; /* skip the '-' */ while(*argv[0]) { switch(*argv[0]) { case '-': nomore=1; break; case 'q': case 'Q': doprint = !doprint; break; case 'x': case 'X': atr = 16 - atr; break; default: fprintf(stderr,"Unsupported switch: %c\n",*argv[0]); fprintf(stderr,"%s "VERSION" by cmwagner@gate.net\n",self); fprintf(stderr,"%s [-qx] input[.dcm] [output[.atr]]\n",self); exit(1); } ++argv[0]; /* We've processed this flag */ } --argc;++argv; /* Done processing these flags */ if(nomore) break; /* Filename may begin with '-' */ } if (argc<1 || argc>2) { fprintf(stderr,"%s "VERSION" by cmwagner@gate.net\n",self); fprintf(stderr,"%s [-qx] input[.dcm] [output[.atr]]\n",self); exit(1); } strcpy(imgin,argv[0]); if (strrchr(imgin,'.') == NULL) strcat(imgin,".dcm"); if (argc==2) strcpy(imgout,argv[1]); else { char *p; strcpy(imgout,imgin); if ((p = strrchr(imgout,'.')) != NULL) *p = 0; } if (strrchr(imgout,'.') == NULL) if (atr) { strcat(imgout,".atr"); } else { strcat(imgout,".xfd"); } if ((fin = fopen(imgin,"rb")) == NULL) { fprintf(stderr,"I couldn't open \"%s\" for reading.\n",imgin); exit(1); } archivetype = blocktype = fgetc(fin); switch(blocktype) { case 0xF9: case 0xFA: break; default: fprintf(stderr,"0x%02X is an unknown header block.\n",blocktype); exit(1); } if ((fout = fopen(imgout,"rb")) != NULL) { fprintf(stderr,"I can't use \"%s\" for output, it already exists.\n",imgout); exit(1); } else { fout = fopen(imgout,"wb"); } rewind(fin); do { if(doprint) printf("\rCurrent sector: %4u",cursec); #ifdef MSDOS if (kbhit()) { if (getch() == 27) { fprintf(stderr,"\nProcessing terminated by user.\n"); exit(1); } } #endif if (feof(fin)) { fflush(stdout); /* Possible buffered I/O confusion fix */ if ((!last) && (blocktype == 0x45) && (archivetype == 0xF9)) { fprintf(stderr,"\nMulti-part archive error.\n"); fprintf(stderr,"To process these files, you must first combine the files into a single file.\n"); #ifdef MSDOS fprintf(stderr,"\tCOPY /B file1.dcm+file2.dcm+file3.dcm newfile.dcm\n"); #else fprintf(stderr,"\tcat file1.dcm file2.dcm file3.dcm > newfile.dcm\n"); #endif } else { fprintf(stderr,"\nEOF before end block.\n"); } exit(1); } tmp = fgetc(fin); /* blocktype is needed on EOF error--don't corrupt it */ if (feof(fin)) continue; /* Will abort on the check at the top of the loop */ blocktype = tmp; switch(blocktype) { case 0xF9: case 0xFA: /* New block */ decode_FA(); break; case 0x45: /* End block */ working=0; if (last) { if (doprint) printf("\r%s has been successfully decompressed.\n",imgout); fclose(fin); fclose(fout); done=1; /* Normal exit */ } break; case 0x41: case 0xC1: decode_C1(); break; case 0x43: case 0xC3: decode_C3(); break; case 0x44: case 0xC4: decode_C4(); break; case 0x46: case 0xC6: decode_C6(); break; case 0x47: case 0xC7: decode_C7(); break; default: fprintf(stderr,"\n0x%02X is an unknown block type. File may be " "corrupt.\n",blocktype); exit(1); } /* end case */ if ((blocktype != 0x45) && (blocktype != 0xFA) && (blocktype != 0xF9)) { if (!(blocktype & 0x80)) { cursec=read_atari16(fin); fseek(fout,soffset(),SEEK_SET); } else { cursec++; } } } while(!done); /* end do */ return(0); /* Should never be executed */ } void decode_C1(void) { int secoff,tmpoff,c; tmpoff=read_offset(fin); c=fgetc(fin); for (secoff=0; secoff> 4); last=((c & 0x80) >> 7); switch(density) { case 0: maxsec=720; secsize=128; break; case 2: maxsec=720; secsize=256; break; case 4: maxsec=1040; secsize=128; break; default: fprintf(stderr,"\nDensity type is unknown, density type=%u\n",density); exit(1); } if (createdisk == 0) { createdisk = 1; if (atr) { /* write out atr header */ /* special code, 0x0296 */ write_atari16(fout,0x296); /* image size (low) */ write_atari16(fout,(short)(((long)maxsec * secsize) >> 4)); /* sector size */ write_atari16(fout,secsize); /* image size (high) */ write_atari16(fout,(short)(((long)maxsec * secsize) >> 20)); /* 8 bytes unused */ write_atari16(fout,0); write_atari16(fout,0); write_atari16(fout,0); write_atari16(fout,0); } memset(buf,0,256); for (cursec=0; cursec