diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..83f818bc --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +CC = gcc +C_FLAGS = -O2 -Wall +L_FLAGS = + +all: dos33 asoft_detoken mkdos33fs make_b + + + +asoft_detoken: asoft_detoken.o + $(CC) $(L_FLAGS) -o asoft_detoken asoft_detoken.o + +asoft_detoken.o: asoft_detoken.c + $(CC) $(C_FLAGS) -c asoft_detoken.c + + + +dos33: dos33.o + $(CC) $(L_FLAGS) -o dos33 dos33.o + +dos33.o: dos33.c dos33.h + $(CC) $(C_FLAGS) -c dos33.c + +make_b: make_b.o + $(CC) $(L_FLAGS) -o make_b make_b.o + +make_b.o: make_b.c + $(CC) $(C_FLAGS) -c make_b.c + + +mkdos33fs: mkdos33fs.o + $(CC) $(L_FLAGS) -o mkdos33fs mkdos33fs.o + +mkdos33fs.o: mkdos33fs.c dos33.h + $(CC) $(C_FLAGS) -c mkdos33fs.c + + +install: + cp dos33 asoft_detoken mkdos33fs make_b /usr/local/bin + +clean: + rm -f *~ *.o asoft_detoken dos33 make_b mkdos33fs diff --git a/TODO b/TODO new file mode 100644 index 00000000..d1bef099 --- /dev/null +++ b/TODO @@ -0,0 +1,6 @@ +check lock before delete + +defrag utility +test-suite + +test mkdosfs copy over DOS functionality diff --git a/asoft_detoken.c b/asoft_detoken.c new file mode 100644 index 00000000..4f7cce7a --- /dev/null +++ b/asoft_detoken.c @@ -0,0 +1,180 @@ +#include +#include /* strlen() */ + + /* Starting at 0x80 */ +char applesoft_tokens[][8]={ + +/* 80 */ "END","FOR","NEXT","DATA","INPUT","DEL","DIM","READ", +/* 88 */ "GR","TEXT","PR #","IN #","CALL","PLOT","HLIN","VLIN", +/* 90 */ "HGR2","HGR","HCOLOR=","HPLOT","DRAW","XDRAW","HTAB","HOME", +/* 98 */ "ROT=","SCALE=","SHLOAD","TRACE","NOTRACE","NORMAL","INVERSE","FLASH", +/* A0 */ "COLOR=","POP","VTAB ","HIMEM:","LOMEM:","ONERR","RESUME","RECALL", +/* A8 */ "STORE","SPEED=","LET","GOTO","RUN","IF","RESTORE","&", +/* B0 */ "GOSUB","RETURN","REM","STOP","ON","WAIT","LOAD","SAVE", +/* B8 */ "DEF FN","POKE","PRINT","CONT","LIST","CLEAR","GET","NEW", +/* C0 */ "TAB","TO","FN","SPC(","THEN","AT","NOT","STEP", +/* C8 */ "+","-","*","/","^","AND","OR",">", +/* D0 */ "=","<","SGN","INT","ABS","USR","FRE","SCRN (", +/* D8 */ "PDL","POS","SQR","RND","LOG","EXP","COS","SIN", +/* E0 */ "TAN","ATN","PEEK","LEN","STR$","VAL","ASC","CHR$", +/* E8 */ "LEFT$","RIGHT$","MID$","","","","","", +/* F0 */ "","","","","","","","", +/* F8 */ "","","","","","(","(","(" +}; + +/* +Integer Basic + + $03: : + $04: LOAD + $05: SAVE + $07: RUN + $09: DEL + $0A: , + $0B: NEW + $0C: CLR + $0D: AUTO + $0F: MAN + $10: HIMEM: + $11: LOMEM: + $12: + + $13: - + $14: * + $15: / + $16: = + $17: # + $18: >= + $19: > + $1A: <= + $1B: <> + $1C: < + $1D: AND + $1E: OR + $1F: MOD + $20: ^ + $22: ( + $23: , + $24, + $25: THEN + $26, + $27: , + $28, $29: \" + $2A: ( + $2D: ( + $2E: PEEK + $2F: RND + $30: SGN + $31: ABS + $32: PDL + $34: ( + $35: + + $36: - + $37: NOT + $38: ( + $39: = + $3A: # + $3B: LEN ( + $3C: ASC ( + $3D: SCRN ( + $3E: , + $3F: ( + $40: $ + $42: ( + $43, + $44: , + $45, + $46, + $47: ; + $48, + $49: , + $4A: , + $4B: TEXT + $4C: GR + $4D: CALL + $4E, + $4F: DIM + $50: TAB + $51: END + $52, $53, $54: INPUT + $55: FOR + $56: = + $57: TO + $58: STEP + $59: NEXT + $5A: , + $5B: RETURN + $5C: GOSUB + $5D: REM + $5E: LET + $5F: GOTO + $60: IF + $61, + $62: PRINT + $63: PRINT + $64: POKE + $65: , + $66: COLOR= + $67: PLOT + $68: , + $69: HLIN + $6A: , + $6B: AT + $6C: VLIN + $6D: , + $6E: AT + $6F: VTAB + $70, + $71: = + $72: ) + $74: LIST + $75: , + $77: POP + $79: NO DSP + $7A: NO TRACE + $7B, + $7C: DSP + $7D: TRACE + $7E: PR # + $7F: IN # + +*/ + + +int main(int argc, char **argv) { + + int ch1,i; + unsigned char size1,size2; + unsigned char line1,line2; + unsigned char eight,line_length; + + + /* read size, first two bytes */ + size1=fgetc(stdin); + size2=fgetc(stdin); + + while(!feof(stdin)) { + + + line_length=fgetc(stdin); + eight=fgetc(stdin); /* sometimes 8, sometimes 9? */ + if (eight==0) goto the_end; + line1=fgetc(stdin); + line2=fgetc(stdin); + if (feof(stdin)) goto the_end; + printf("%4d ",(((int)line2)<<8)+line1); + + while( (ch1=fgetc(stdin))!=0 ) { + if (ch1>=0x80) { + fputc(' ',stdout); + for(i=0;i +#include /* exit() */ +#include /* strncpy() */ +#include /* struct stat */ +#include /* O_RDONLY */ +#include /* lseek() */ +#include /* toupper() */ + +#define VERSION "0.4" + +#include "dos33.h" + +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, +}; + +unsigned char dos33_file_type(int value) { + + unsigned char result; + + switch(value){ + case 0x0: result='T'; break; + case 0x1: result='I'; break; + case 0x2: result='A'; break; + case 0x4: result='B'; break; + case 0x8: result='S'; break; + case 0x10: result='R'; break; + case 0x20: result='N'; break; + case 0x40: result='L'; break; + default: result='?'; break; + } + return result; +} + + +unsigned char dos33_char_to_type(char type,int lock) { + + unsigned char result,temp_type; + + temp_type=type; + /* Covert to upper case */ + if (temp_type>='a') temp_type=temp_type-0x20; + + switch(temp_type) { + case 'T': result=0x0; break; + case 'I': result=0x1; break; + case 'A': result=0x2; break; + case 'B': result=0x4; break; + case 'S': result=0x8; break; + case 'R': result=0x10; break; + case 'N': result=0x20; break; + case 'L': result=0x40; break; + default: result=0x0; + } + if (lock) result|=0x80; + return result; +} + + /* dos33 filenames have top bit set on ascii chars */ + /* and are padded with spaces */ +char *dos33_filename_to_ascii(unsigned char *dest,unsigned char *src) { + + int i=0,last_nonspace=0; + + for(i=0;i<30;i++) if (src[i]!=0xA0) last_nonspace=i; + + for(i=0;i>4)&0xf]; + sectors_free+=ones_lookup[bitmap[1]&0xf]; + sectors_free+=ones_lookup[(bitmap[1]>>4)&0xf]; + +// printf("%i: 0x%x 0x%x\n",i,bitmap[0],bitmap[1]); + + + } + + return sectors_free*BYTES_PER_SECTOR; +} + + + +int dos33_get_catalog_ts(int fd,unsigned char *buffer) { + dos33_read_vtoc(fd,buffer); + + return TS_TO_INT(buffer[VTOC_CATALOG_T],buffer[VTOC_CATALOG_S]); +} + +int dos33_find_next_file(int fd,int catalog_tsf,unsigned char *buffer) { + + + int catalog_track,catalog_sector,catalog_file; + int file_track,i; + + catalog_file=catalog_tsf>>16; + catalog_track=(catalog_tsf>>8)&0xff; + catalog_sector=(catalog_tsf&0xff); + +catalog_loop: + + /* Read in Catalog Sector */ + lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + i=catalog_file; + while(i<7) { + + file_track=buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]; + /* 0xff means file deleted */ + /* 0x0 means empty */ + if ((file_track!=0xff) && (file_track!=0x0)){ + return ((i<<16)+(catalog_track<<8)+catalog_sector); + } + i++; + } + catalog_track=buffer[CATALOG_NEXT_T]; + catalog_sector=buffer[CATALOG_NEXT_S]; + if (catalog_sector!=0) goto catalog_loop; + return -1; +} + +int dos33_print_file_info(int fd,int catalog_tsf,unsigned char *buffer) { + + int catalog_track,catalog_sector,catalog_file; + char temp_string[BUFSIZ]; + + catalog_file=catalog_tsf>>16; + catalog_track=(catalog_tsf>>8)&0xff; + catalog_sector=(catalog_tsf&0xff); + + + /* Read in Catalog Sector */ + lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + if (buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f) { + printf("*"); + } + else printf(" "); + + printf("%c",dos33_file_type(buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE])); + printf(" "); + printf("%.3i ",buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_SIZE_L)]+ + (buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_SIZE_H)]<<8)); + + + printf("%s",dos33_filename_to_ascii(temp_string, + buffer+(CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_NAME)))); + + printf("\n"); + + return 0; +} + + +int dos33_check_file_exists(int fd,char *filename,unsigned char *buffer) { + + int catalog_track=0,catalog_sector=0; + int i,file_track; + char file_name[31]; + + dos33_read_vtoc(fd,buffer); + + catalog_track=buffer[VTOC_CATALOG_T]; + catalog_sector=buffer[VTOC_CATALOG_S]; + +repeat_catalog: + + /* Read in Catalog Sector */ + lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + for(i=0;i<7;i++) { + file_track=buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]; + /* 0xff means file deleted */ + /* 0x0 means empty */ + if ((file_track!=0xff) && (file_track!=0x0)){ + + dos33_filename_to_ascii(file_name, + buffer+(CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE+FILE_NAME))); + + if (!strncmp(filename,file_name,30)) return ((i<<16)+(catalog_track<<8)+catalog_sector); + } + + } + catalog_track=buffer[CATALOG_NEXT_T]; + catalog_sector=buffer[CATALOG_NEXT_S]; + + if (catalog_sector!=0) goto repeat_catalog; + + return -1; +} + +int find_first_one(unsigned char byte) { + + int i=0; + + while((byte& (0x1<VTOC_TRACK) && (track_dir!=1)) || + ((start_track=TRACKS_PER_DISK) { + i=VTOC_TRACK; + track_dir=-1; + } + + } while (i!=start_track); + + printf("No room left!\n"); + return -1; + +found_one: + /* store new track/direction info */ + buffer[VTOC_LAST_ALLOC_T]=found_track; + + if (found_track>VTOC_TRACK) buffer[VTOC_ALLOC_DIRECT]=1; + else buffer[VTOC_ALLOC_DIRECT]=-1; + + /* Seek to VTOC */ + lseek(fd,DISK_OFFSET(VTOC_TRACK,VTOC_SECTOR),SEEK_SET); + /* Write out VTOC */ + write(fd,&buffer,BYTES_PER_SECTOR); + return ((found_track<<8)+found_sector); +} + +int dos33_add_file(int fd,char type,char *filename,char *apple_filename, + unsigned char *buffer) { + + int free_space,file_size; + struct stat file_info; + int size_in_sectors=0; + int initial_ts_list=0,ts_list=0,i,data_ts,x,bytes_read=0,old_ts_list; + int catalog_track,catalog_sector,sectors_used=0; + int input_fd; + + /* FIXME */ + /* check type */ + /* and sanity check a/b filesize is set properly */ + + + + /* Determine size of file to upload */ + if (stat(filename,&file_info)<0) { + printf("Error! %s not found!\n",filename); + exit(3); + } + file_size=(int)file_info.st_size; + + /* Get free space on device */ + free_space=dos33_free_space(fd,buffer); + + /* Check for free space */ + /* Really, this is not enough. */ + /* We need an extra sector for a T/S list every 122*256 bytes (~31k) */ + if (file_size>free_space) { + printf("Error! Not enough free space on disk image\n"); + } + + /* plus one because we need a sector for the tail */ + size_in_sectors=(file_size/BYTES_PER_SECTOR)+1; + printf("Need to allocate %i data sectors\n",size_in_sectors); + + /* Open the local file */ + input_fd=open(filename,O_RDONLY); + if (input_fd<0) { + printf("Error! could not open %s\n",filename); + return -1; + } + + + + i=0; + while (i>8)&0xff,ts_list&0xff),SEEK_SET); + write(fd,buffer,BYTES_PER_SECTOR); + + if (i==0) initial_ts_list=ts_list; + else { + /* we aren't the first t/s list so do special stuff */ + + /* load in the old t/s list */ + lseek(fd,DISK_OFFSET((old_ts_list>>8)&0xff,old_ts_list&0xff),SEEK_SET); + read(fd,&buffer,BYTES_PER_SECTOR); + + /* point from old ts list to new one we just made */ + buffer[TSL_NEXT_TRACK]=(ts_list>>8)&0xff; + buffer[TSL_NEXT_SECTOR]=(ts_list)&0xff; + + /* set offset into file */ + buffer[TSL_OFFSET_H]=(((i-122)*256)>>8)&0xff; + buffer[TSL_OFFSET_L]=(((i-122)*256)&0xff); + + /* write out the old t/s list with updated info */ + lseek(fd,DISK_OFFSET((old_ts_list>>8)&0xff,old_ts_list&0xff),SEEK_SET); + write(fd,buffer,BYTES_PER_SECTOR); + } + } + + + /* allocate a sector */ + data_ts=dos33_allocate_sector(fd); + sectors_used++; + + if (data_ts<0) return -1; + + /* clear sector */ + for(x=0;x>8)&0xff,data_ts&0xff),SEEK_SET); + write(fd,buffer,BYTES_PER_SECTOR); +// printf("Writing %i bytes to %i/%i\n",bytes_read,(data_ts>>8)&0xff, +// data_ts&0xff); + + + + /* add to T/s table */ + + /* read in t/s list */ + lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + /* point to new data sector */ + buffer[((i%TSL_MAX_NUMBER)*2)+TSL_LIST]=(data_ts>>8)&0xff; + buffer[((i%TSL_MAX_NUMBER)*2)+TSL_LIST+1]=(data_ts&0xff); + + /* write t/s list back out */ + lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET); + write(fd,buffer,BYTES_PER_SECTOR); + + i++; + } + + /* Add new file to Catalog */ + + /* read in vtoc */ + dos33_read_vtoc(fd,buffer); + + catalog_track=buffer[VTOC_CATALOG_T]; + catalog_sector=buffer[VTOC_CATALOG_S]; + +continue_parsing_catalog: + + /* Read in Catalog Sector */ + lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + /* Find empty directory entry */ + i=0; + while(i<7) { + if ((buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]==0xff) || + (buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]==0x00)) + goto got_a_dentry; + i++; + } + + if ((catalog_track=0x11) && (catalog_sector==1)) { + /* in theory can only have 105 files */ + /* if full, we have no recourse! */ + /* can we allocate new catalog sectors and point to them?? */ + printf("Error! No more room for files!\n"); + return -1; + } + + catalog_track=buffer[CATALOG_NEXT_T]; + catalog_sector=buffer[CATALOG_NEXT_S]; + + goto continue_parsing_catalog; + +got_a_dentry: +// printf("Adding file at entry %i of catalog 0x%x:0x%x\n", +// i,catalog_track,catalog_sector); + + /* Point entry to initial t/s list */ + buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]=(initial_ts_list>>8)&0xff; + buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+1]=(initial_ts_list&0xff); + /* set file type */ + buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_TYPE]= + dos33_char_to_type(type,0); + +// printf("Pointing T/S to %x/%x\n",(initial_ts_list>>8)&0xff,initial_ts_list&0xff); + + /* copy over filename */ + for(x=0;x>8)&0xff; + + /* write out catalog sector */ + lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET); + write(fd,buffer,BYTES_PER_SECTOR); + + return 0; +} + +int dos33_load_file(int fd,int fts,char *filename,unsigned char *buffer) { + + int output_fd; + int catalog_file,catalog_track,catalog_sector; + int file_type,file_size=-1,tsl_track,tsl_sector,data_t,data_s; + unsigned char data_sector[BYTES_PER_SECTOR]; + int tsl_pointer=0,output_pointer=0; + + output_fd=open(filename,O_WRONLY|O_CREAT,0666); + if (output_fd<0) { + printf("Error! could not open %s for local save\n",filename); + return -1; + } + + catalog_file=fts>>16; + catalog_track=(fts>>8)&0xff; + catalog_sector=(fts&0xff); + + + /* Read in Catalog Sector */ + lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + tsl_track=buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TS_LIST_T]; + tsl_sector=buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TS_LIST_S]; + file_type=dos33_file_type(buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]); + + printf("file_type: %c\n",file_type); + +keep_savin: + /* Read in TSL Sector */ + lseek(fd,DISK_OFFSET(tsl_track,tsl_sector),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + + while(tsl_pointer=0) { + ftruncate(output_fd,file_size); + } + + return 0; + +} + + +int dos33_delete_file(int fd,int fsl,unsigned char *buffer) { + + int i; + int catalog_track,catalog_sector,catalog_entry; + int ts_track,ts_sector; + + /* unpack file/track/sector info */ + catalog_entry=fsl>>16; + catalog_track=(fsl>>8)&0xff; + catalog_sector=(fsl&0xff); + + /* Load in the catalog table for the file */ + lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + /* get pointer to t/s list */ + ts_track=buffer[CATALOG_FILE_LIST+catalog_entry*CATALOG_ENTRY_SIZE+ + FILE_TS_LIST_T]; + ts_sector=buffer[CATALOG_FILE_LIST+catalog_entry*CATALOG_ENTRY_SIZE+ + FILE_TS_LIST_S]; + +keep_deleting: + + + + /* load in the t/s list info */ + lseek(fd,DISK_OFFSET(ts_track,ts_sector),SEEK_SET); + read(fd,buffer,BYTES_PER_SECTOR); + + /* Free each sector listed by t/s list */ + for(i=0;i\n"); + printf("\n"); + printf("Usage: %s disk_image COMMAND\n",name); + printf(" Where disk_image is a valid dos3.3 disk image\n" + " and COMMAND is one of the following:\n"); + printf("\tCATALOG\n"); + printf("\tLOAD apple_file \n"); + printf("\n"); + return 0; +} + +#define COMMAND_UNKNOWN 0 +#define COMMAND_LOAD 1 +#define COMMAND_SAVE 2 +#define COMMAND_BLOAD 3 +#define COMMAND_BSAVE 4 +#define COMMAND_CATALOG 5 +#define COMMAND_DELETE 6 +#define COMMAND_UNDELETE 7 +#define COMMAND_LOCK 8 +#define COMMAND_UNLOCK 9 +#define COMMAND_INIT 10 +#define COMMAND_UPLOAD 11 +#define COMMAND_DNLOAD 12 +#define COMMAND_VERIFY 13 +#define COMMAND_RENAME 14 +#define COMMAND_COPY 15 + +int main(int argc, char **argv) { + + char image[BUFSIZ]; + unsigned char type='b'; + int dos_fd=0,i; + + int command,catalog; + char temp_string[BUFSIZ]; + char apple_filename[31]; + char output_filename[BUFSIZ]; + + unsigned char scratch_sector[BYTES_PER_SECTOR]; + + if (argc<3) { + printf("\nInvalid arguments!\n"); + display_help(argv[0]); + goto exit_program; + } + + strncpy(temp_string,argv[2],BUFSIZ); + for(i=0;i30) { + printf("Warning! Truncating %s to 30 chars\n",argv[3]); + } + strncpy(apple_filename,argv[3],30); + apple_filename[31]='\0'; + + if (argc==5) { + strncpy(output_filename,argv[4],BUFSIZ); + } + else { + strncpy(output_filename,apple_filename,30); + } + + catalog=dos33_check_file_exists(dos_fd,apple_filename,scratch_sector); + if (catalog<0) { + printf("Error! %s not found!\n",apple_filename); + goto exit_and_close; + } + + dos33_load_file(dos_fd,catalog,output_filename,scratch_sector); + + + break; + case COMMAND_CATALOG: + + /* get first catalog */ + catalog=dos33_get_catalog_ts(dos_fd,scratch_sector); + + printf("\nDISK VOLUME %i\n\n",scratch_sector[VTOC_DISK_VOLUME]); + while(catalog>0) { + catalog=dos33_find_next_file(dos_fd,catalog,scratch_sector); + if (catalog>0) { + dos33_print_file_info(dos_fd,catalog,scratch_sector); + catalog+=(1<<16); + } + } + printf("\n"); + break; + + case COMMAND_SAVE: + + /* argv3 == type == A,B,T,I, N,L etc */ + /* argv4 == name of local file */ + /* argv5 == optional name of file on disk image */ + + if (argc<5) { + printf("Error! Need type and file_name\n"); + printf("%s %s SAVE type file_name apple_filename\n",argv[0],image); + goto exit_and_close; + } + + type=argv[3][0]; + + if (argc==6) { + if (strlen(argv[5])>30) { + printf("Warning! Truncating filename to 30 chars!\n"); + } + strncpy(apple_filename,argv[5],30); + apple_filename[31]=0; + } + else { + if (strlen(argv[4])>30) { + printf("Warning! Truncating filename to 30 chars!\n"); + } + strncpy(apple_filename,argv[4],30); + apple_filename[31]=0; + } + + catalog=dos33_check_file_exists(dos_fd,apple_filename,scratch_sector); + if (catalog>=0) { + printf("Warning! %s exists!\n",apple_filename); + printf("Over-write (y/n)?"); + fgets(temp_string,BUFSIZ,stdin); + if (temp_string[0]!='y') { + printf("Exiting early...\n"); + goto exit_and_close; + } + printf("Deleting previous version...\n"); + dos33_delete_file(dos_fd,catalog,scratch_sector); + } + + dos33_add_file(dos_fd,type,argv[4],apple_filename,scratch_sector); + + + break; + case COMMAND_BSAVE: + + case COMMAND_DELETE: + if (argc<4) { + printf("Error! Need file_name\n"); + printf("%s %s DELETE apple_filename\n",argv[0],image); + goto exit_and_close; + } + catalog=dos33_check_file_exists(dos_fd,argv[3],scratch_sector); + if (catalog<0) { + printf("Error! File %s does not exist\n",argv[3]); + goto exit_and_close; + } + dos33_delete_file(dos_fd,catalog,scratch_sector); + break; + + case COMMAND_UNDELETE: + case COMMAND_LOCK: + case COMMAND_UNLOCK: + case COMMAND_INIT: + case COMMAND_UPLOAD: + case COMMAND_DNLOAD: + case COMMAND_VERIFY: + case COMMAND_RENAME: + case COMMAND_COPY: + default: + printf("Sorry, unsupported command\n"); + goto exit_and_close; + } +#if 0 + + + + type=argv[3][0]; + + if (type<'a') type+=0x20; + if ((type!='a') && (type!='b') && (type!='t')) { + printf("Error! Type must be A, B, or T!\n"); + exit(2); + } + + printf("Adding \"%s\" to image \"%s\" type %c\n\n", + filename,image,type); + + + if (dos33_check_file_exists(dos_fd,filename)) { + char temp_input[BUFSIZ]; + printf("Error! File %s already exists on %s!\n",filename,image); + printf("Overwrite? (y/n)"); + scanf("%s",temp_input); + if (temp_input[0]=='y') { + dos33_delete_file(dos_fd,filename); + printf("Deleting old file %s\n",filename); + exit(5); + } + else { + exit(5); + } + } + + dos33_add_file(dos_fd,filename,file_size,type); +#endif + + +exit_and_close: + close(dos_fd); +exit_program: + + return 0; +} diff --git a/dos33.h b/dos33.h new file mode 100644 index 00000000..805fe6cf --- /dev/null +++ b/dos33.h @@ -0,0 +1,54 @@ + /* For now hard-coded */ + /* Could be made dynamic if we want to be useful */ + /* On dos3.2 disks, or larger filesystems */ +#define TRACKS_PER_DISK 0x23 +#define SECTORS_PER_TRACK 0x10 +#define BYTES_PER_SECTOR 0x100 + +#define VTOC_TRACK 0x11 +#define VTOC_SECTOR 0x00 + + /* VTOC Values */ +#define VTOC_CATALOG_T 0x1 +#define VTOC_CATALOG_S 0x2 +#define VTOC_DOS_RELEASE 0x3 +#define VTOC_DISK_VOLUME 0x6 +#define VTOC_MAX_TS_PAIRS 0x27 +#define VTOC_LAST_ALLOC_T 0x30 +#define VTOC_ALLOC_DIRECT 0x31 +#define VTOC_NUM_TRACKS 0x34 +#define VTOC_S_PER_TRACK 0x35 +#define VTOC_BYTES_PER_SL 0x36 +#define VTOC_BYTES_PER_SH 0x37 +#define VTOC_FREE_BITMAPS 0x38 + + /* CATALOG_VALUES */ +#define CATALOG_NEXT_T 0x01 +#define CATALOG_NEXT_S 0x02 +#define CATALOG_FILE_LIST 0x0b + +#define CATALOG_ENTRY_SIZE 0x23 + + /* CATALOG ENTRY */ +#define FILE_TS_LIST_T 0x0 +#define FILE_TS_LIST_S 0x1 +#define FILE_TYPE 0x2 +#define FILE_NAME 0x3 +#define FILE_SIZE_L 0x21 +#define FILE_SIZE_H 0x22 + +#define FILE_NAME_SIZE 0x1e + + /* TSL */ +#define TSL_NEXT_TRACK 0x1 +#define TSL_NEXT_SECTOR 0x2 +#define TSL_OFFSET_L 0x5 +#define TSL_OFFSET_H 0x6 +#define TSL_LIST 0xC + +#define TSL_ENTRY_SIZE 0x2 +#define TSL_MAX_NUMBER 122 + + /* Helper Macros */ +#define TS_TO_INT(__x,__y) ((((int)__x)<<8)+__y) +#define DISK_OFFSET(__track,__sector) ((((__track)*SECTORS_PER_TRACK)+(__sector))*BYTES_PER_SECTOR) diff --git a/make_b.c b/make_b.c new file mode 100644 index 00000000..6ee70e3b --- /dev/null +++ b/make_b.c @@ -0,0 +1,58 @@ +#include +#include /* struct stat */ +#include /* exit() */ +#include /* open() */ +#include /* close() */ + +int main(int argc, char **argv) { + + int in_fd,out_fd,offset; + + unsigned char buffer[256]; + int result,file_size; + + struct stat file_info; + + if (argc!=4) { + printf("Usage: %s in_file out_file offset\n\n",argv[0]); + printf("\tin_file : input file\n"); + printf("\tout_file : output file\n"); + printf("\toffset : offset which file should be loaded\n\n"); + exit(1); + } + + if (stat(argv[1],&file_info)<0) { + printf("Error! %s not found!\n",argv[1]); + exit(2); + } + file_size=(int)file_info.st_size; + + if ((in_fd=open(argv[1],O_RDONLY))<0) { + printf("Error opening %s!\n",argv[1]); + exit(3); + } + + if ((out_fd=open(argv[2],O_WRONLY|O_CREAT,0666))<0) { + printf("Error opening %s\n",argv[2]); + exit(4); + } + + offset=strtol(argv[3],NULL,0); + + buffer[0]=offset&0xff; + buffer[1]=(offset>>8)&0xff; + buffer[2]=file_size&0xff; + buffer[3]=(file_size>>8)&0xff; + + write(out_fd,&buffer,4); + + while( (result=read(in_fd,&buffer,256))>0) { + write(out_fd,&buffer,result); + } + + + close(in_fd); + close(out_fd); + + return 0; +} diff --git a/mkdos33fs.c b/mkdos33fs.c new file mode 100644 index 00000000..a5043dbf --- /dev/null +++ b/mkdos33fs.c @@ -0,0 +1,196 @@ +#include +#include /* strncpy() */ +#include /* open() */ +#include /* close() */ +#include /* strtol() */ + +#include "dos33.h" + +#define VERSION "0.0.1" + +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 [-t track] [-s sector] [-b size] " + "[-d 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-d filename : file to copy first 3 tracks over from\n"); + printf("\n\n"); + } + exit(0); + return; +} + +int main(int argc, char **argv) { + + int num_tracks=35,num_sectors=16,block_size=256; + int fd,dos_fd; + char device[BUFSIZ],dos_src[BUFSIZ]; + char *buffer,*endptr; + int i,c,copy_dos=0; + + + + /* Parse Command Line Arguments */ + + while ((c = getopt (argc, argv,"t:s:b:d:hv"))!=-1) { + switch (c) { + + 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': block_size=strtol(optarg,&endptr,10); + if ( endptr == optarg ) usage(argv[0], 1); + break; + + case 'd': copy_dos=1; + strncpy(dos_src,optarg,BUFSIZ); + 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); + + /* Sanity check values */ + + /* s 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; + } + + /* t 17->(block_size-0x38)/2 */ + if ((num_tracks<18) || (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?) */ + 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); + + /* Open device */ + fd=open(device,O_WRONLY|O_CREAT,0666); + if (fd<0) { + fprintf(stderr,"Error opening %s\n",device); + goto end_of_program; + } + + /* zero out file */ + for(i=0;i524 */ + buffer[VTOC_LAST_ALLOC_T]=18; /* 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; + + 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; + } + + /* reserve track 17 */ + /* 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; + + + + /* Write out VTOC to disk */ + lseek(fd,((17*num_sectors)+0)*block_size,SEEK_SET); + write(fd,buffer,block_size); + + + + + close(fd); + +end_of_program: + + return 0; +}