/* converts a raw disk image file into a dos-order disk image */ /* Copyright (c) 1996 by Christopher Bachmann (c-bachmann@nwu.edu) Feel free to redistribute it, port it, copy it around, but if you change it, improve it, base something else on it, etc. Please let me know, so that I can keep this up to date, and incorporate the best of everything. */ #include /*static unsigned char disk[35][16][343]; /* encoded data, checksum */ static unsigned char raw_track[16][343]; /*static unsigned char output[35][16][256]; /* decoded output disk */ static unsigned char decoded_track[16][256]; static long int start[35]; /* start positions for each track */ static long int length[35]; /* length of each track */ static int track; static int sector; unsigned char translation[] = { 0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, 0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; unsigned char interleave[] = { 0x00, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04, 0x0B, 0x03, 0x0A, 0x02, 0x09, 0x01, 0x08, 0x0F }; unsigned char reverse[] = {0x00, 0x02, 0x01, 0x03}; /* open the file for reading as binary */ FILE *openfile(char *filename) { FILE *fileno; fileno = fopen(filename, "rb"); return fileno; } /* read in information from the header */ void readheader (FILE *fileid) { int i; fseek (fileid, (long) 0x2b0, 0); /* point to first data field */ for (i=0; i < 35; i++) { start[i] = 0; start[i] = ((((long) getc (fileid)) & 0xff) << 16) | start[i]; start[i] = ((((long) getc (fileid)) & 0xff) << 8) | start[i]; start[i] = ((((long) getc (fileid)) & 0xff)) | start[i]; start[i] = ((((long) getc (fileid)) & 0xff) << 24) | start[i]; /* start[i] = ((getc(fileid) & 0xff) << 16) | ((getc(fileid) & 0xff) << 8) | ((getc(fileid) & 0xff)) | ((getc(fileid) & 0xff) << 24); */ /* printf ("%x ",start[i]); */ } printf ("\n"); fseek (fileid, (long) 0x440, 0); for (i=0; i < 35; i++) { length[i] = 0; length[i] = ((((long) getc (fileid)) & 0xff)) | length[i]; length[i] = ((((long) getc (fileid)) & 0xff) << 8) | length[i]; length[i] = ((((long) getc (fileid)) & 0xff) << 16) | length[i]; length[i] = ((((long) getc (fileid)) & 0xff) << 24) | length[i]; /* length[i] = ((getc(fileid) & 0xff)) | ((getc(fileid) & 0xff) << 8) | ((getc(fileid) & 0xff) << 16) | ((getc(fileid) & 0xff) << 24); */ /* printf ("%x ",length[i]); */ } /* printf ("\n"); */ } /* print the short as 4 hex digits, with a line number */ void printbyte (short number) { int high,low; high = (number >> 8) & 0xff; low = number & 0xff; /* if (high < 16) printf ("0%x",high); else printf ("%x",high); */ if (low < 16) printf ("0%x ",low); else printf ("%x ",low); } /* print address information */ void print_address (int *address) { int i; int volume; volume = (address[3] << 1 & 0xff | 0x01) & (address[4] & 0xff); track = (address[5] << 1 & 0xff | 0x01) & (address[6] & 0xff); sector = (address[7] << 1 & 0xff | 0x01) & (address[8] & 0xff); /* printf ("Address: V%x T%x S%x\n",volume,track,sector); */ } /* print output data information */ void print_output () { int i; for (i=0; i < 256; i++) { /* printf ("%x ",output[track][interleave[sector]][i]); */ printf ("%x ",decoded_track[interleave[sector]][i]); } printf ("\n"); } /* print sector data information */ void print_data (unsigned char *data) { int i,j; for (i=0; i < 343; i++) { printf ("%x ",data[i]); } printf ("\n"); } /* finds the address header, and reads in the current track/sector */ read_address(FILE *fileid) { int address[14]; /* address information */ int done = 0; /* flag */ int buffer = 0xffff; /* bit buffer (like apple latch) */ int input_byte; /* input byte */ int input_bit; /* current bit */ int bit_count; /* number of bits shifted in so far */ int index=0; /* index into address array */ while (!done) { input_byte = getc(fileid); if (input_byte == EOF) { /* check for end of file ?? */ done = 1; } else { for (input_bit = 0; input_bit < 8; input_bit++) { /* get current bit */ buffer = ((buffer << 1) & 0xfffe) | ((input_byte >> 7) & 1); input_byte = input_byte << 1; /* update count */ bit_count++; /* test for valid data */ if ((bit_count >= 8) && ((buffer & 0x0080) != 0)) { /* printbyte (buffer); */ /* find prolog of address block */ if ((index != 0) && (index < 3)){ address[index++] = (buffer & 0xff); if (address[1] != 0xAA) { /* make sure address prolog */ index = 0; } if (index == 3) { if (address[2] != 0x96) { /* make sure address prolog */ index = 0; } } } else if (index == 0) { /* searching for 0xD5 */ if ((buffer & 0xff) == 0xD5) { address[index++] = 0xD5; } } else { /* reading address information */ address[index++] = (buffer & 0xff); if (index == 14) { done = 1; input_bit = 8; } } bit_count = 0; /* reset bit counter */ buffer = 0xffff; /* and buffer */ } /* end valid data */ } /* end current byte */ } /* end EOF test */ } /* end while loop */ print_address(address); /* display current address */ } /* finds the next data sector, and reads the encoded version in */ find_data(FILE *fileid) { int prolog[3]; /* prolog information */ int done = 0; /* flag */ int buffer = 0xffff; /* bit buffer (like apple latch) */ int input_byte; /* input byte */ int input_bit; /* current bit */ int bit_count; /* number of bits shifted in so far */ int index=0; /* index into prolog array */ int dataindex=0; /* index into sector array */ while (!done) { input_byte = getc(fileid); if (input_byte == EOF) { /* check for end of file ?? */ done = 1; } else { for (input_bit = 0; input_bit < 8; input_bit++) { /* get current bit */ buffer = ((buffer << 1) & 0xfffe) | ((input_byte >> 7) & 1); input_byte = input_byte << 1; /* update count */ bit_count++; /* test for valid data */ if ((bit_count >= 8) && ((buffer & 0x0080) != 0)) { /* printbyte (buffer); */ /* find prolog of data block */ if ((index != 0) && (index < 3)){ prolog[index++] = (buffer & 0xff); if (prolog[1] != 0xAA) { /* make sure data prolog */ index = 0; } if (index == 3) { if (prolog[2] != 0xAD) { /* make sure data prolog */ index = 0; } } } else if (index == 0) { /* searching for 0xD5 */ if ((buffer & 0xff) == 0xD5) { prolog[index++] = 0xD5; } } else { /* reading data information */ /* disk[track][sector][dataindex++] = (buffer & 0xff); */ raw_track[sector][dataindex++] = (buffer & 0xff); if (dataindex == 343) { done = 1; input_bit = 8; } } bit_count = 0; /* reset bit counter */ buffer = 0xffff; /* and buffer */ } /* end valid data */ } /* end current byte */ } /* end EOF test */ } /* end while loop */ /* print_data(disk[track][sector]); */ /* print_data(raw_track[sector]); */ } /* decode the data and put it into the output disk */ void decode_data() { int i,j; int check; /* checksum */ unsigned char low[86]; /* temporary values */ unsigned char high[256]; unsigned char temp_output[256]; /* temporary output */ check = 0; /* first translate raw bytes, and compute checksum */ for (i=0;i<86;i++) { j = 0; /* while (translation[j] != disk[track][sector][i]) */ while (translation[j] != raw_track[sector][i]) j++; check = j^check; low[i] = check; } for (i=86;i<342;i++) { j = 0; /* while (translation[j] != disk[track][sector][i]) */ while (translation[j] != raw_track[sector][i]) j++; check = j^check; high[i-86] = check << 2; } j = 0; /* while (translation[j] != disk[track][sector][342]) */ while (translation[j] != raw_track[sector][342]) j++; check = check^j; /* checksum should equal zero */ if (check != 0) { printf ("Error Track %d Sector %d: Checksum invalid = %d\n", track,sector,check); } /* decode bytes and store them into the buffer */ for (i=0; i<256; i++) { temp_output[i] = 0; if (i<86) temp_output[i] = (high[i] | reverse[(low[i]&0x03)]); else if (i<172) temp_output[i] = (high[i] | reverse[((low[i-86]&0x0C)>>2)]); else temp_output[i] = (high[i] | reverse[((low[i-172]&0x30)>>4)]); } /* copy the bytes into the right sector on the disk */ for (i=0; i<256; i++) { /* output[track][interleave[sector]][i] = temp_output[i]; */ decoded_track[interleave[sector]][i] = temp_output[i]; } /* print_output(); */ } /* process a single track into encoded disk */ void read_track(FILE *fileid) { int i; for (i=0; i < 16; i++) { read_address(fileid); /* find the address */ find_data(fileid); /* find next data */ decode_data(); /* get the decoded data */ } } /* process the file as if we are a real apple reading the disk */ void process(FILE *fileid, char *filename) { FILE *fileno; int trk; /* track */ int j,k; /* sector/byte */ printf ("Processing "); fileno = fopen(filename, "wb"); for (trk=0; trk < 35; trk++) { /* printf ("Track %d\n",trk); */ printf ("."); fseek (fileid, start[trk], 0); /* seek to start of track */ read_track(fileid); /* read in track */ for (j=0;j<16;j++) { for (k=0;k<256;k++) { /* fprintf (fileno,"%c",decoded_track[j][k]); */ putc (decoded_track[j][k],fileno); } } } fclose (fileno); printf ("Done\n"); } /* close the file after reading */ void closefile(FILE *fileid) { fclose (fileid); } void main(int argc, char *argv[]) { char *filename; FILE *fileid; if (argc < 3) { printf ("img2dsk \n"); } else { fileid = openfile(argv[1]); if (fileid == NULL) { printf ("Filename not found\n"); } else { readheader (fileid); process (fileid, argv[2]); closefile(fileid); } } }