prodos: VOLUME command now works

This commit is contained in:
Vince Weaver 2021-08-02 13:37:50 -04:00
parent 2570ecc0e2
commit 58f22f7119
4 changed files with 159 additions and 11 deletions

View File

@ -825,6 +825,7 @@ static void display_help(char *name, int version_only) {
printf("\tDELETE apple_file\n");
printf("\tRENAME apple_file_old apple_file_new\n");
printf("\tDUMP\n");
printf("\tVOLUME volume_name\n");
printf("\tTYPE TODO: set type\n");
printf("\tAUX TODO: set aux\n");
printf("\tTIMESTAMP TODO: set timestamp\n");
@ -834,18 +835,19 @@ static void display_help(char *name, int version_only) {
return;
}
#define COMMAND_LOAD 0
#define COMMAND_SAVE 1
#define COMMAND_CATALOG 2
#define COMMAND_DELETE 3
#define COMMAND_RENAME 4
#define COMMAND_DUMP 5
#define COMMAND_BSAVE 6
#define COMMAND_BLOAD 7
#define COMMAND_LOAD 0
#define COMMAND_SAVE 1
#define COMMAND_CATALOG 2
#define COMMAND_DELETE 3
#define COMMAND_RENAME 4
#define COMMAND_DUMP 5
#define COMMAND_BSAVE 6
#define COMMAND_BLOAD 7
#define COMMAND_SHOWFREE 8
#define COMMAND_VOLNAME 9
#define MAX_COMMAND 9
#define COMMAND_UNKNOWN 255
#define MAX_COMMAND 10
#define COMMAND_UNKNOWN 255
static struct command_type {
int type;
@ -860,6 +862,7 @@ static struct command_type {
{COMMAND_BSAVE,"BSAVE"},
{COMMAND_BLOAD,"BLOAD"},
{COMMAND_SHOWFREE,"SHOWFREE"},
{COMMAND_VOLNAME,"VOLNAME"},
};
static int lookup_command(char *name) {
@ -891,6 +894,67 @@ static int truncate_filename(char *out, char *in) {
return truncated;
}
static int prodos_sync_voldir(struct voldir_t *voldir) {
unsigned char newvoldir[PRODOS_BYTES_PER_BLOCK];
memset(newvoldir,0,PRODOS_BYTES_PER_BLOCK);
newvoldir[0x4]=(voldir->storage_type<<4)|(voldir->name_length&0xf);
memcpy(&newvoldir[0x5],voldir->volume_name,voldir->name_length);
/* FIXME: probably endianess issues */
newvoldir[0x1c]=(voldir->creation_time>>16)&0xff;
newvoldir[0x1d]=(voldir->creation_time>>24)&0xff;
newvoldir[0x1e]=(voldir->creation_time>>0)&0xff;
newvoldir[0x1f]=(voldir->creation_time>>8)&0xff;
newvoldir[0x20]=voldir->version;
newvoldir[0x21]=voldir->min_version;
newvoldir[0x22]=voldir->access;
newvoldir[0x23]=voldir->entry_length;
newvoldir[0x24]=voldir->entries_per_block;
newvoldir[0x25]=voldir->file_count&0xff;
newvoldir[0x26]=(voldir->file_count>>8)&0xff;
newvoldir[0x27]=voldir->bit_map_pointer&0xff;
newvoldir[0x28]=(voldir->bit_map_pointer>>8)&0xff;
newvoldir[0x29]=voldir->total_blocks&0xff;
newvoldir[0x2A]=(voldir->total_blocks>>8)&0xff;
newvoldir[0x2]=voldir->next_block&0xff;
newvoldir[0x3]=(voldir->next_block>>8)&0xff;
prodos_write_block(voldir,newvoldir,PRODOS_VOLDIR_KEY_BLOCK);
return 0;
}
static int change_volume_name(struct voldir_t *voldir, char *volname) {
int volname_len;
volname_len=strlen(volname);
if (volname_len>15) {
printf("Warning! Volume name %s is too long, truncating\n",
volname);
volname_len=15;
}
memcpy(voldir->volume_name,volname,15);
voldir->name_length=volname_len;
prodos_sync_voldir(voldir);
return 0;
}
int main(int argc, char **argv) {
char image[BUFSIZ];
@ -912,7 +976,7 @@ int main(int argc, char **argv) {
struct voldir_t voldir;
/* Check command line arguments */
while ((c = getopt (argc, argv,"a:i:l:t:s:dhvxy"))!=-1) {
while ((c = getopt (argc, argv,"a:i:l:dhvxy"))!=-1) {
switch (c) {
case 'd':
@ -1327,6 +1391,23 @@ int main(int argc, char **argv) {
break;
/* Change the volume name */
case COMMAND_VOLNAME:
/* check and make sure we have a volume name */
if (argc==optind) {
fprintf(stderr,"Error! Need apple volume_name\n");
fprintf(stderr,"%s %s VOLUME volume_name\n",
argv[0],image);
goto exit_and_close;
}
change_volume_name(&voldir,argv[optind]);
break;
default:
fprintf(stderr,"Sorry, unsupported command %s\n\n",temp_string);
goto exit_and_close;

View File

@ -121,3 +121,4 @@ int prodos_showfree(struct voldir_t *voldir, int fd);
/* prodos_read.c */
int prodos_read_block(struct voldir_t *voldir,unsigned char *block, int blocknum);
int prodos_write_block(struct voldir_t *voldir,unsigned char *block, int blocknum);

View File

@ -79,3 +79,64 @@ int prodos_read_block(struct voldir_t *voldir,
return 0;
}
int prodos_write_block(struct voldir_t *voldir,
unsigned char *block, int blocknum) {
int result=0;
int track,sector1,sector2;
if (voldir->interleave==PRODOS_INTERLEAVE_PRODOS) {
/* Seek to VOLDIR */
lseek(voldir->fd,voldir->image_offset+
blocknum*PRODOS_BYTES_PER_BLOCK,SEEK_SET);
result=write(voldir->fd,block,PRODOS_BYTES_PER_BLOCK);
if (result<PRODOS_BYTES_PER_BLOCK) {
fprintf(stderr,"Error writing block $%X\n",blocknum);
return -1;
}
}
else if (voldir->interleave==PRODOS_INTERLEAVE_DOS33) {
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<<4)+sector1)*256);
lseek(voldir->fd,voldir->image_offset+
((track<<4)+sector1)*256,SEEK_SET);
result=write(voldir->fd,block,PRODOS_BYTES_PER_BLOCK/2);
if (result<PRODOS_BYTES_PER_BLOCK/2) {
fprintf(stderr,"Error writing block $%X (%X)\n",
blocknum,((track<<4)+sector1));
return -1;
}
if (debug) printf("Seeking to %x\n",((track<<4)+sector2)*256);
lseek(voldir->fd,voldir->image_offset+
((track<<4)+sector2)*256,SEEK_SET);
result=write(voldir->fd,block+256,PRODOS_BYTES_PER_BLOCK/2);
if (result<PRODOS_BYTES_PER_BLOCK/2) {
fprintf(stderr,"Error writing block $%X (%X)\n",
blocknum,((track<<4)+sector2));
return -1;
}
}
else {
fprintf(stderr,"ERROR! Unknown interleave!\n");
}
return 0;
}

View File

@ -0,0 +1,5 @@
Tests:
+ check dump before/after VOLUME change be sure only len/name change
+ store/load various sized files, md5sum or compare results