diff --git a/utils/dos33fs-utils/Makefile b/utils/dos33fs-utils/Makefile index 896bb1e9..427d6e52 100644 --- a/utils/dos33fs-utils/Makefile +++ b/utils/dos33fs-utils/Makefile @@ -6,15 +6,15 @@ all: dos33 mkdos33fs make_b \ char2hex: char2hex.o - $(CC) $(LFLAGS) -o char2hex char2hex.o + $(CC) -o char2hex char2hex.o $(LFLAGS) char2hex.o: char2hex.c $(CC) $(CFLAGS) -c char2hex.c ### -dos33: dos33.o - $(CC) $(LFLAGS) -o dos33 dos33.o +dos33: dos33.o dos33_vtoc_bitmap.o + $(CC) -o dos33 dos33.o dos33_vtoc_bitmap.o $(LFLAGS) dos33.o: dos33.c dos33.h $(CC) $(CFLAGS) -g -c dos33.c @@ -22,7 +22,7 @@ dos33.o: dos33.c dos33.h ### dos33_raw: dos33_raw.o - $(CC) $(LFLAGS) -o dos33_raw dos33_raw.o + $(CC) -o dos33_raw dos33_raw.o $(LFLAGS) dos33_raw.o: dos33_raw.c $(CC) $(CFLAGS) -g -c dos33_raw.c @@ -30,23 +30,35 @@ dos33_raw.o: dos33_raw.c ### dos33_text2ascii: dos33_text2ascii.o - $(CC) $(LFLGAS) -o dos33_text2ascii dos33_text2ascii.o + $(CC) -o dos33_text2ascii dos33_text2ascii.o $(LFLAGS) dos33_text2ascii.o: dos33_text2ascii.c $(CC) $(CFLAGS) -c dos33_text2ascii.c +### + make_b: make_b.o - $(CC) $(LFLAGS) -o make_b make_b.o + $(CC) -o make_b make_b.o $(LFLAGS) make_b.o: make_b.c $(CC) $(CFLAGS) -c make_b.c -mkdos33fs: mkdos33fs.o - $(CC) $(LFLAGS) -o mkdos33fs mkdos33fs.o +### + +mkdos33fs: mkdos33fs.o dos33_vtoc_bitmap.o + $(CC) $(LFLAGS) -o mkdos33fs mkdos33fs.o \ + dos33_vtoc_bitmap.o mkdos33fs.o: mkdos33fs.c dos33.h $(CC) $(CFLAGS) -c mkdos33fs.c +### + +dos33_vtoc_bitmap.o: dos33_vtoc_bitmap.c dos33.h + $(CC) $(CFLAGS) -c dos33_vtoc_bitmap.c + +### + install: cp dos33 dos33_raw mkdos33fs make_b dos33_text2ascii char2hex $(INSTALL_LOC) diff --git a/utils/dos33fs-utils/dos33.c b/utils/dos33fs-utils/dos33.c index 17a427ef..01614b51 100644 --- a/utils/dos33fs-utils/dos33.c +++ b/utils/dos33fs-utils/dos33.c @@ -5,6 +5,7 @@ #include /* O_RDONLY */ #include /* lseek() */ #include /* toupper() */ +#include #include "version.h" @@ -14,25 +15,6 @@ static int debug=0,ignore_errors=0; static unsigned char sector_buffer[BYTES_PER_SECTOR]; -static int ones_lookup[16]={ - /* 0x0 = 0000 */ 0, - /* 0x1 = 0001 */ 1, - /* 0x2 = 0010 */ 1, - /* 0x3 = 0011 */ 2, - /* 0x4 = 0100 */ 1, - /* 0x5 = 0101 */ 2, - /* 0x6 = 0110 */ 2, - /* 0x7 = 0111 */ 3, - /* 0x8 = 1000 */ 1, - /* 0x9 = 1001 */ 2, - /* 0xA = 1010 */ 2, - /* 0xB = 1011 */ 3, - /* 0xC = 1100 */ 2, - /* 0xd = 1101 */ 3, - /* 0xe = 1110 */ 3, - /* 0xf = 1111 */ 4, -}; - static unsigned char get_high_byte(int value) { return (value>>8)&0xff; } @@ -122,23 +104,10 @@ static int dos33_read_vtoc(int fd) { /* Calculate available freespace */ static int dos33_free_space(int fd) { - unsigned char bitmap[4]; - int i,sectors_free=0; - /* Read Vtoc */ dos33_read_vtoc(fd); - for(i=0;i>4)&0xf]; - sectors_free+=ones_lookup[bitmap[1]&0xf]; - sectors_free+=ones_lookup[(bitmap[1]>>4)&0xf]; - } - - return sectors_free*BYTES_PER_SECTOR; + return dos33_vtoc_free_space(sector_buffer); } @@ -303,21 +272,6 @@ repeat_catalog: return -1; } - /* could be replaced by "find leading 1" instruction */ - /* if available */ -static int find_first_one(unsigned char byte) { - - int i=0; - - if (byte==0) return -1; - - while((byte& (0x1<VTOC_TRACK) && (track_dir!=1)) || - ((start_track-1;byte--) { - bitmap[byte]=sector_buffer[VTOC_FREE_BITMAPS+(i*4)+byte]; - if (bitmap[byte]!=0x00) { - found_sector=find_first_one(bitmap[byte]); - found_track=i; - /* clear bit indicating in use */ - sector_buffer[VTOC_FREE_BITMAPS+(i*4)+byte]&=~(0x1<=TRACKS_PER_DISK) { - i=VTOC_TRACK; - track_dir=-1; - } - } while (i!=start_track); - - fprintf(stderr,"No room left!\n"); - return -1; - -found_one: /* store new track/direction info */ sector_buffer[VTOC_LAST_ALLOC_T]=found_track; @@ -429,7 +335,7 @@ static int dos33_force_allocate_sector(int fd) { int found_track=0,found_sector=0; //unsigned char bitmap[4]; int i,start_track;//,track_dir,byte; - int result,so; + int result; dos33_read_vtoc(fd); @@ -441,14 +347,13 @@ static int dos33_force_allocate_sector(int fd) { start_track=track; i=start_track; - so=!(sector/8); - found_sector=sector%8; // FIXME: check if free //bitmap[so]=sector_buffer[VTOC_FREE_BITMAPS+(i*4)+so]; /* clear bit indicating in use */ - sector_buffer[VTOC_FREE_BITMAPS+(i*4)+so]&=~(0x1< + +#include "dos33.h" + +static int ones_lookup[16]={ + /* 0x0 = 0000 */ 0, + /* 0x1 = 0001 */ 1, + /* 0x2 = 0010 */ 1, + /* 0x3 = 0011 */ 2, + /* 0x4 = 0100 */ 1, + /* 0x5 = 0101 */ 2, + /* 0x6 = 0110 */ 2, + /* 0x7 = 0111 */ 3, + /* 0x8 = 1000 */ 1, + /* 0x9 = 1001 */ 2, + /* 0xA = 1010 */ 2, + /* 0xB = 1011 */ 3, + /* 0xC = 1100 */ 2, + /* 0xD = 1101 */ 3, + /* 0xE = 1110 */ 3, + /* 0xF = 1111 */ 4, +}; + + /* could be replaced by "find leading 1" instruction */ + /* if available */ +static int find_first_one(unsigned char byte) { + + int i=0; + + if (byte==0) return -1; + + while((byte & (0x1<>4)&0xf]; + sectors_free+=ones_lookup[bitmap[1]&0xf]; + sectors_free+=ones_lookup[(bitmap[1]>>4)&0xf]; + } + + return sectors_free*BYTES_PER_SECTOR; +} + +/* free a sector from the sector bitmap */ +void dos33_vtoc_free_sector(unsigned char *vtoc, int track, int sector) { + + /* each bitmap is 32 bits. With 16-sector tracks only first 16 used */ + /* 1 indicates free, 0 indicates used */ + if (sector<8) { + vtoc[VTOC_FREE_BITMAPS+(track*4)+1]|=(0x1<VTOC_TRACK) && (track_dir!=1)) || + ((start_track=TRACKS_PER_DISK) { + i=VTOC_TRACK; + track_dir=-1; + } + } while (i!=start_track); + + if (found) { + /* clear bit indicating in use */ + dos33_vtoc_reserve_sector(vtoc, *found_track, *found_sector); + + return 0; + } + + /* no room */ + return -1; + +} diff --git a/utils/dos33fs-utils/mkdos33fs.c b/utils/dos33fs-utils/mkdos33fs.c index 432b809b..30f5cce6 100644 --- a/utils/dos33fs-utils/mkdos33fs.c +++ b/utils/dos33fs-utils/mkdos33fs.c @@ -3,6 +3,8 @@ #include /* open() */ #include /* close() */ #include /* strtol() */ +#include + #include "version.h" #include "dos33.h" @@ -15,11 +17,13 @@ static void usage(char *binary,int help) { if (help) { printf("Usage:\t%s [-t track] [-s sector] [-b size] " "[-d filename] [-f filename] device_name\n\n",binary); - printf("\t-t tracks : number of tracks in filesystem\n"); - printf("\t-s sectors : number of sectors in filesystem\n"); - printf("\t-b blocksize : size of sector, in bytes\n"); + 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-d 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); @@ -29,9 +33,11 @@ static void usage(char *binary,int help) { int main(int argc, char **argv) { int num_tracks=35,num_sectors=16,block_size=256; + int max_files=105,catalog_track=17,vtoc_track=17,volume_number=254; + int max_ts_pairs=255; int fd,dos_fd; char device[BUFSIZ],dos_src[BUFSIZ]; - char *buffer,*endptr; + char *vtoc_buffer=NULL,*sector_buffer=NULL,*endptr; int i,c,copy_dos=0; int result; @@ -39,7 +45,7 @@ int main(int argc, char **argv) { /* Parse Command Line Arguments */ - while ((c = getopt (argc, argv,"t:s:b:d:f:hv"))!=-1) { + while ((c = getopt (argc, argv,"t:s:b:d:f:m:n:hv"))!=-1) { switch (c) { case 't': @@ -56,6 +62,17 @@ int main(int argc, char **argv) { block_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 'd': copy_dos=1; strncpy(dos_src,optarg,BUFSIZ-1); @@ -89,33 +106,118 @@ int main(int argc, char **argv) { goto end_of_program; } - /* t 17->(block_size-0x38)/2 */ - if ((num_tracks<18) || (num_tracks>(block_size-0x38)/2)) { + /* t 1 ->(block_size-0x38)/2 */ + if ((num_tracks<1) || (num_tracks>(block_size-0x38)/2)) { printf("Number of tracks must be >18 and <=%i (block_size-0x38)/2\n\n", (block_size-0x38)/2); goto end_of_program; } - /* sector_size 256->65536 (or 512 basedon one bye t/s size field?) */ + /* sector_size 256->65536 (or 512 based on one byte t/s size field?) */ if ((block_size<256)||(block_size>65536)) { printf("Block size must be >=256 and <65536\n\n"); goto end_of_program; } - buffer=calloc(1,sizeof(char)*block_size); + /* allocate space for buffers */ + vtoc_buffer=calloc(1,sizeof(char)*block_size); + if (vtoc_buffer==NULL) { + fprintf(stderr,"Error allocating memory!\n"); + goto end_of_program; + } - /* Open device */ + sector_buffer=calloc(1,sizeof(char)*block_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\n",device); + 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=((block_size-0xc)/2); + if (max_ts_pairs>255) { + printf("Warning! Truncating max_ts pairs to 255\n"); + max_ts_pairs=255; + } + + /***************/ + /* 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 block_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]=block_size&0xff; + vtoc_buffer[VTOC_BYTES_PER_SH]=(block_size>>8)&0xff; + + /* Set sector bitmap so whole disk is free */ + for(i=VTOC_FREE_BITMAPS;i16) { + vtoc_buffer[i+2]=0xff; + vtoc_buffer[i+3]=0xff; + } + } + + /* Copy over OS from elsewhere, if desired */ if (copy_dos) { dos_fd=open(dos_src,O_RDONLY); @@ -126,8 +228,8 @@ int main(int argc, char **argv) { lseek(fd,0,SEEK_SET); /* copy first 3 sectors */ for(i=0;i<3*(num_sectors);i++) { - result=read(dos_fd,buffer,block_size); - result=write(fd,buffer,block_size); + result=read(dos_fd,vtoc_buffer,block_size); + result=write(fd,vtoc_buffer,block_size); } close(dos_fd); @@ -135,94 +237,71 @@ int main(int argc, char **argv) { /* Track 1 sector 9 */ lseek(fd,((1*num_sectors)+9)*block_size,SEEK_SET); - result=read(fd,buffer,block_size); + result=read(fd,vtoc_buffer,block_size); /* filename begins at offset 75 */ for(i=0;i<30;i++) { - buffer[0x75+i]=boot_filename[i]|0x80; + vtoc_buffer[0x75+i]=boot_filename[i]|0x80; } lseek(fd,((1*num_sectors)+9)*block_size,SEEK_SET); - result=write(fd,buffer,block_size); + result=write(fd,vtoc_buffer,block_size); } - /* clear buffer */ - for(i=0;i524 */ - buffer[VTOC_LAST_ALLOC_T]=0x12; /* last track space was allocated */ - /* Start at middle, work way out */ - buffer[VTOC_ALLOC_DIRECT]=1; /* Working our way outward */ - buffer[VTOC_NUM_TRACKS]=num_tracks; - buffer[VTOC_S_PER_TRACK]=num_sectors; - buffer[VTOC_BYTES_PER_SL]=block_size&0xff; - buffer[VTOC_BYTES_PER_SH]=(block_size>>8)&0xff; - - /* Set sector bitmap so whole disk is free */ - for(i=VTOC_FREE_BITMAPS;i16) { - buffer[i+2]=0xff; - buffer[i+3]=0xff; - } - } /* reserve track 0 */ /* No user data can be stored here as track=0 is special case */ /* end of file indicator */ - buffer[VTOC_FREE_BITMAPS]=0x00; - buffer[VTOC_FREE_BITMAPS+1]=0x00; - buffer[VTOC_FREE_BITMAPS+2]=0x00; - buffer[VTOC_FREE_BITMAPS+3]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+1]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+2]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+3]=0x00; /* if copying dos reserve tracks 1 and 2 as well */ if (copy_dos) { - buffer[VTOC_FREE_BITMAPS+4]=0x00; - buffer[VTOC_FREE_BITMAPS+5]=0x00; - buffer[VTOC_FREE_BITMAPS+6]=0x00; - buffer[VTOC_FREE_BITMAPS+7]=0x00; - buffer[VTOC_FREE_BITMAPS+8]=0x00; - buffer[VTOC_FREE_BITMAPS+9]=0x00; - buffer[VTOC_FREE_BITMAPS+10]=0x00; - buffer[VTOC_FREE_BITMAPS+11]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+4]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+5]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+6]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+7]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+8]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+9]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+10]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+11]=0x00; } /* reserve track 17 (0x11) */ /* reserved for vtoc and catalog stuff */ - buffer[VTOC_FREE_BITMAPS+17*4]=0x00; - buffer[VTOC_FREE_BITMAPS+17*4+1]=0x00; - buffer[VTOC_FREE_BITMAPS+17*4+2]=0x00; - buffer[VTOC_FREE_BITMAPS+17*4+3]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+17*4]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+17*4+1]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+17*4+2]=0x00; + vtoc_buffer[VTOC_FREE_BITMAPS+17*4+3]=0x00; + /**************************/ /* Write out VTOC to disk */ - lseek(fd,((17*num_sectors)+0)*block_size,SEEK_SET); + /**************************/ + lseek(fd,((vtoc_track*num_sectors)+0)*block_size,SEEK_SET); - result=write(fd,buffer,block_size); - if (result<0) fprintf(stderr,"Error writing!\n"); + result=write(fd,vtoc_buffer,block_size); + if (result<0) { + fprintf(stderr,"Error writing VTOC (%s)!\n",strerror(errno)); + } - /* clear buffer */ - for(i=0;i1;i--) { - buffer[1]=0x11; - buffer[2]=i-1; + vtoc_buffer[1]=0x11; + vtoc_buffer[2]=i-1; lseek(fd,((17*num_sectors)+i)*block_size,SEEK_SET); - result=write(fd,buffer,block_size); + result=write(fd,vtoc_buffer,block_size); if (result<0) fprintf(stderr,"Error writing!\n"); } close(fd); end_of_program: + if (vtoc_buffer) free(vtoc_buffer); + if (sector_buffer) free(sector_buffer); + return 0; }