#include #include /* strncpy() */ #include /* open() */ #include /* close() */ #include /* strtol() */ #include #include "version.h" #include "dos33.h" int debug=0; static void usage(char *binary,int help) { printf("\n%s - version %s\n",binary,VERSION); printf("\tby Vince Weaver \n"); printf("\thttp://www.deater.net/weave/vmwprod/apple/\n\n"); if (help) { printf("Usage:\t%s [-d debug] [-t track] [-s sector] [-b size] " "[-i filename] [-f filename] device_name\n\n",binary); printf("\t-t tracks : number of tracks (default is 35)\n"); printf("\t-s sectors : number of sectors (default is 16)\n"); printf("\t-b blocksize : size of sector, in bytes (default is 256)\n"); printf("\t-i filename : file to copy first 3 tracks over from\n"); printf("\t-f filename : name of BASIC file to autoboot. Default is HELLO\n"); printf("\t-m maxfiles : maximum files in CATALOG (default is 105)\n"); printf("\t-n volume : volume number (default is 254)\n"); printf("\n\n"); } exit(0); return; } int main(int argc, char **argv) { int num_tracks=35,num_sectors=16,sector_size=256; int max_files=105,catalog_track=17,vtoc_track=17,volume_number=254; int catalog_sectors,current_sector,current_track; int next_track,next_sector; int max_ts_pairs=255; int fd,dos_fd; char device[BUFSIZ],dos_src[BUFSIZ]; unsigned char *vtoc_buffer=NULL,*sector_buffer=NULL; char *endptr; int i,c,copy_dos=0; int result; char boot_filename[30]="HELLO "; /* Parse Command Line Arguments */ while ((c = getopt (argc, argv,"t:s:b:df:i:m:n:hv"))!=-1) { switch (c) { case 'd': debug=1; break; case 't': num_tracks=strtol(optarg,&endptr,10); if ( endptr == optarg ) usage(argv[0], 1); break; case 's': num_sectors=strtol(optarg,&endptr,10); if ( endptr == optarg ) usage(argv[0], 1); break; case 'b': sector_size=strtol(optarg,&endptr,10); if ( endptr == optarg ) usage(argv[0], 1); break; case 'm': max_files=strtol(optarg,&endptr,10); if ( endptr == optarg ) usage(argv[0], 1); break; case 'n': volume_number=strtol(optarg,&endptr,10); if ( endptr == optarg ) usage(argv[0], 1); break; case 'i': copy_dos=1; strncpy(dos_src,optarg,BUFSIZ-1); break; case 'f': if (strlen(optarg)>30) { fprintf(stderr,"Auto boot filename too long!\n"); exit(1); } memcpy(boot_filename,optarg,strlen(optarg)); for(i=strlen(optarg);i<30;i++) boot_filename[i]=' '; // printf("Writing boot filename \"%s\"\n",boot_filename); break; case 'v': usage(argv[0],0); case 'h': usage(argv[0],1); } } if (optind==argc) { printf("Error! Must include device name\n\n"); goto end_of_program; } strncpy(device,argv[optind],BUFSIZ-1); /***********************/ /* Sanity check values */ /***********************/ /* sectors: 2->32 (limited by 4-byte bitfields) */ if ((num_sectors<2) || (num_sectors>32)) { printf("Number of sectors must be >2 and <=32\n\n"); goto end_of_program; } /* tracks 18-50 ->(sector_size-0x38)/4 */ /* limited by VTOC room for freespace bitmap (which is $38 to $ff) */ /* VOTC is always on track 17 so we need at least that many */ /* though could double if we used the unused sector fields */ if ((num_tracks(sector_size-0x38)/4)) { printf("Number of tracks must be >%d and <=%i\n\n", vtoc_track,(sector_size-0x38)/4); goto end_of_program; } /* sector_size 256->65536 (or 512 based on one byte t/s size field?) */ if ((sector_size<256)||(sector_size>65536)) { printf("Block size must be >=256 and <65536\n\n"); goto end_of_program; } /* allocate space for buffers */ vtoc_buffer=calloc(1,sizeof(char)*sector_size); if (vtoc_buffer==NULL) { fprintf(stderr,"Error allocating memory!\n"); goto end_of_program; } sector_buffer=calloc(1,sizeof(char)*sector_size); if (sector_buffer==NULL) { fprintf(stderr,"Error allocating memory!\n"); goto end_of_program; } /* Open device */ fd=open(device,O_RDWR|O_CREAT,0666); if (fd<0) { fprintf(stderr,"Error opening %s (%s)\n", device,strerror(errno)); goto end_of_program; } /* zero out file */ for(i=0;i255) { printf("Warning! Truncating volume number %d to %d\n", volume_number,volume_number&0xff); volume_number&=0xff; } if (catalog_track>num_tracks) { printf("Warning! Catalog track too high! Adjusting...\n"); catalog_track=(num_tracks/2)+1; } if (vtoc_track>num_tracks) { printf("Warning! VTOC track too high! Adjusting...\n"); vtoc_track=(num_tracks/2)+1; } if (vtoc_track!=17) { printf("Warning! VTOC track is %d, not 17, so unpatched DOS won't be able to find it!\n", vtoc_track); } max_ts_pairs=((sector_size-0xc)/2); if (max_ts_pairs>255) { printf("Warning! Truncating max_ts pairs to 255\n"); max_ts_pairs=255; } /* default is 105 files (15 catalog sectors) */ catalog_sectors=max_files/7; if (max_files%7) catalog_sectors++; if (catalog_sectors>num_sectors-1) { printf("Warning! num_files higher than normal %d sectors, ususal is %d\n",catalog_sectors,num_sectors-1); } /***************/ /* Create VTOC */ /***************/ /* fake dos 3.3 */ vtoc_buffer[VTOC_DOS_RELEASE]=0x3; /* 1st Catalog typically at 0x11/0xf */ vtoc_buffer[VTOC_CATALOG_T]=catalog_track; vtoc_buffer[VTOC_CATALOG_S]=num_sectors-1; /* typically volume is 254 */ vtoc_buffer[VTOC_DISK_VOLUME]=volume_number; /* Number of T/S pairs fitting */ /* in a T/S list sector */ /* Note, overflows if sector_size>524 */ vtoc_buffer[VTOC_MAX_TS_PAIRS]=max_ts_pairs; /* last track space was allocated on */ /* so filesystem can try to do things in order */ /* also start at catalog track and work our way outward */ vtoc_buffer[VTOC_LAST_ALLOC_T]=catalog_track+1; vtoc_buffer[VTOC_ALLOC_DIRECT]=1; vtoc_buffer[VTOC_NUM_TRACKS]=num_tracks; vtoc_buffer[VTOC_S_PER_TRACK]=num_sectors; vtoc_buffer[VTOC_BYTES_PER_SL]=sector_size&0xff; vtoc_buffer[VTOC_BYTES_PER_SH]=(sector_size>>8)&0xff; /* Set sector bitmap so whole disk is free */ for(i=0;i16) { vtoc_buffer[VTOC_FREE_BITMAPS+(i*4)+2]=0xff; vtoc_buffer[VTOC_FREE_BITMAPS+(i*4)+3]=0xff; } } /* Copy over OS from elsewhere, if desired */ if (copy_dos) { dos_fd=open(dos_src,O_RDONLY); if (fd<0) { fprintf(stderr,"Error opening %s\n",dos_src); goto end_of_program; } lseek(fd,0,SEEK_SET); /* copy first 3 sectors */ for(i=0;i<3*(num_sectors);i++) { result=read(dos_fd,sector_buffer,sector_size); result=write(fd,sector_buffer,sector_size); } close(dos_fd); /* Set boot filename */ /* Track 1 sector 9 */ lseek(fd,((1*num_sectors)+9)*sector_size,SEEK_SET); result=read(fd,sector_buffer,sector_size); /* filename begins at offset 75 */ for(i=0;i<30;i++) { sector_buffer[0x75+i]=boot_filename[i]|0x80; } lseek(fd,((1*num_sectors)+9)*sector_size,SEEK_SET); result=write(fd,sector_buffer,sector_size); /* if copying dos reserve tracks 1 and 2 as well */ for(i=0;i