From 0cba4da69186d67df8f5e82cd525bcdfb7cafc47 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Sun, 1 Aug 2021 19:11:09 -0400 Subject: [PATCH] prodos: LOAD of a seed file works now the DOS33 interleave support was horribly broken --- utils/prodos-utils/Makefile | 2 + utils/prodos-utils/mkprodosfs.c | 2 + utils/prodos-utils/prodos.c | 142 +++++++++++++++++++++++++++---- utils/prodos-utils/prodos_read.c | 27 +++--- 4 files changed, 145 insertions(+), 28 deletions(-) diff --git a/utils/prodos-utils/Makefile b/utils/prodos-utils/Makefile index 2c7aaa78..e6d4a6ae 100644 --- a/utils/prodos-utils/Makefile +++ b/utils/prodos-utils/Makefile @@ -1,5 +1,7 @@ include ../../Makefile.inc +CFLAGS := $(CFLAGS) -g + all: prodos mkprodosfs ### diff --git a/utils/prodos-utils/mkprodosfs.c b/utils/prodos-utils/mkprodosfs.c index cbc26442..d1d6a342 100644 --- a/utils/prodos-utils/mkprodosfs.c +++ b/utils/prodos-utils/mkprodosfs.c @@ -9,6 +9,8 @@ #include "prodos.h" +int debug=0; + static void usage(char *binary,int help) { printf("\n%s - version %s\n",binary,VERSION); diff --git a/utils/prodos-utils/prodos.c b/utils/prodos-utils/prodos.c index dc947942..258ae754 100644 --- a/utils/prodos-utils/prodos.c +++ b/utils/prodos-utils/prodos.c @@ -11,8 +11,8 @@ #include "prodos.h" -static int debug=0,ignore_errors=0; - +static int ignore_errors=0; +int debug=1; /* Read volume directory into a buffer */ static int prodos_read_voldir(int fd, struct voldir_t *voldir, int interleave) { @@ -67,6 +67,52 @@ static int prodos_read_voldir(int fd, struct voldir_t *voldir, int interleave) { } + /* Given filename, return voldir/offset */ +static int prodos_lookup_file(struct voldir_t *voldir, + char *filename) { + + int voldir_block,voldir_offset; + struct file_entry_t file_entry; + unsigned char voldir_buffer[PRODOS_BYTES_PER_BLOCK]; + int result,file; + + voldir_block=PRODOS_VOLDIR_KEY_BLOCK; + voldir_offset=1; /* skip the header */ + + while(1) { + + /* Read in Block */ + result=prodos_read_block(voldir, + voldir_buffer,voldir_block); + if (result<0) { + fprintf(stderr,"Error on I/O\n"); + return -1; + } + + for(file=voldir_offset; + fileentries_per_block;file++) { + + prodos_populate_filedesc( + voldir_buffer+4+file*PRODOS_FILE_DESC_LEN, + &file_entry); + + /* FIXME: case insensitive? */ + if (!strncmp(filename,(char *)file_entry.file_name,15)) { + return (voldir_block<<8)|file; + } + } + + voldir_offset=0; + voldir_block=voldir_buffer[2]|(voldir_buffer[3]<<8); + if (voldir_block==0) break; + + } + + return -1; +} + + + /* Checks if "filename" exists */ /* returns file type */ static int prodos_check_file_exists(struct voldir_t *voldir, @@ -432,17 +478,40 @@ got_a_dentry: } - /* load a file from the disk image. */ +int prodos_get_file_entry(struct voldir_t *voldir, + int inode, struct file_entry_t *file) { + + unsigned char voldir_buffer[PRODOS_BYTES_PER_BLOCK]; + int block,offset; + int result; + + block=(inode>>8); + offset=(inode&0xff); + + + result=prodos_read_block(voldir,voldir_buffer,block); + if (result<0) { + return result; + } + + prodos_populate_filedesc(voldir_buffer+4+offset*PRODOS_FILE_DESC_LEN, + file); + + return 0; + + +} + + /* load a file from the disk image. */ + /* inode = voldirblock<<8 | entry */ static int prodos_load_file(struct voldir_t *voldir, int inode,char *filename) { 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[PRODOS_BYTES_PER_BLOCK]; + unsigned char data[PRODOS_BYTES_PER_BLOCK]; unsigned char sector_buffer[PRODOS_BYTES_PER_BLOCK]; - int tsl_pointer=0,output_pointer=0; int result; + struct file_entry_t file; /* FIXME! Warn if overwriting file! */ output_fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666); @@ -452,6 +521,44 @@ static int prodos_load_file(struct voldir_t *voldir, return -1; } + if (prodos_get_file_entry(voldir,inode,&file)<0) { + fprintf(stderr,"Error opening inode %x\n",inode); + return -1; + } + + + switch(file.storage_type) { + case PRODOS_FILE_SEEDLING: + /* Just a single block */ + if (debug) fprintf(stderr,"Loading %d bytes from " + "block $%x\n", + file.eof,file.key_pointer); + result=prodos_read_block(voldir,data, + file.key_pointer); + if (result<0) { + return result; + } + result=write(output_fd,data,file.eof); + if (result!=file.eof) { + fprintf(stderr,"Error writing file!\n"); + return -1; + } + break; + + case PRODOS_FILE_SAPLING: + case PRODOS_FILE_TREE: + case PRODOS_FILE_SUBDIR: + + case PRODOS_FILE_DELETED: + case PRODOS_FILE_SUBDIR_HDR: + case PRODOS_FILE_VOLUME_HDR: + default: + fprintf(stderr,"Error! " + "Cannot load this type of file: %x\n", + file.storage_type); + break; + } + #if 0 keep_saving: /* Read in TSL Sector */ @@ -762,6 +869,7 @@ int main(int argc, char **argv) { int always_yes=0; char *temp,*endptr; int c; + int inode; int address=0, length=0; struct voldir_t voldir; struct file_entry_t file; @@ -825,7 +933,7 @@ int main(int argc, char **argv) { /* Try to autodetch interleave based on filename */ if (strlen(image)>4) { if (!strncmp(&image[strlen(image)-4],".dsk",4)) { - if (debug) printf("Detected DOS33\n"); + if (debug) printf("Detected DOS33 interleave\n"); interleave=PRODOS_INTERLEAVE_DOS33; } } @@ -895,18 +1003,18 @@ int main(int argc, char **argv) { if (debug) printf("\tOutput filename: %s\n",local_filename); + /* get the voldir/entry for file */ + inode=prodos_lookup_file(&voldir,apple_filename); - /* get the entry/track/sector for file */ - catalog_entry=prodos_check_file_exists(prodos_fd, - apple_filename, - DOS33_FILE_NORMAL); - if (catalog_entry<0) { + if (inode<0) { fprintf(stderr,"Error! %s not found!\n", apple_filename); goto exit_and_close; } - prodos_load_file(prodos_fd,catalog_entry,local_filename); + + /* Load the file */ + prodos_load_file(&voldir,inode,local_filename); break; @@ -983,7 +1091,7 @@ int main(int argc, char **argv) { if (debug) printf("\tApple filename: %s\n",apple_filename); - catalog_entry=prodos_check_file_exists(prodos_fd,apple_filename, + catalog_entry=prodos_check_file_exists(&voldir,apple_filename, DOS33_FILE_NORMAL); if (catalog_entry>=0) { @@ -1024,7 +1132,7 @@ int main(int argc, char **argv) { truncate_filename(apple_filename,argv[optind]); - catalog_entry=prodos_check_file_exists(prodos_fd, + catalog_entry=prodos_check_file_exists(&voldir, apple_filename, DOS33_FILE_NORMAL); if (catalog_entry<0) { @@ -1071,7 +1179,7 @@ int main(int argc, char **argv) { truncate_filename(new_filename,argv[optind]); /* get the entry/track/sector for file */ - catalog_entry=prodos_check_file_exists(prodos_fd, + catalog_entry=prodos_check_file_exists(&voldir, apple_filename, DOS33_FILE_NORMAL); if (catalog_entry<0) { diff --git a/utils/prodos-utils/prodos_read.c b/utils/prodos-utils/prodos_read.c index a10560ed..0c1b5979 100644 --- a/utils/prodos-utils/prodos_read.c +++ b/utils/prodos-utils/prodos_read.c @@ -11,7 +11,7 @@ #include "prodos.h" -static int debug=0; +extern int debug; /* we want block 2 -> 0xb */ static int dos_interleave[16]= { @@ -35,30 +35,35 @@ int prodos_read_block(struct voldir_t *voldir, result=read(voldir->fd,block,PRODOS_BYTES_PER_BLOCK); if (resultinterleave==PRODOS_INTERLEAVE_DOS33) { - if (debug) printf("DOS33! reading %d\n",blocknum); - track=blocknum&(~0xf); - sector1=dos_interleave[(blocknum&0xf)*2]; - sector2=dos_interleave[(blocknum&0xf)*2+1]; + if (debug) printf("Using DOS33 interleave, finding block $%X\n",blocknum); + track=(blocknum>>3); + sector1=dos_interleave[(blocknum&0x7)*2]; + sector2=dos_interleave[(blocknum&0x7)*2+1]; + if (debug) printf("Remapping block $%X to T%d S%d and T%d S%d\n", + blocknum,track,sector1,track,sector2); - if (debug) printf("Seeking to %x\n",(track+sector1)*256); - lseek(voldir->fd,(track+sector1)*256,SEEK_SET); + if (debug) printf("Seeking to %x\n",((track<<4)+sector1)*256); + lseek(voldir->fd,((track<<4)+sector1)*256,SEEK_SET); result=read(voldir->fd,block,PRODOS_BYTES_PER_BLOCK/2); if (resultfd,(track+sector2)*256,SEEK_SET); + if (debug) printf("Seeking to %x\n",((track<<4)+sector2)*256); + lseek(voldir->fd,((track<<4)+sector2)*256,SEEK_SET); result=read(voldir->fd,block+256,PRODOS_BYTES_PER_BLOCK/2); if (result