prodos: mkprodosfs vaguely working

This commit is contained in:
Vince Weaver 2021-08-03 16:09:41 -04:00
parent 5e04bbf227
commit 2e0f87162f
5 changed files with 307 additions and 383 deletions

View File

@ -10,12 +10,14 @@ prodos: prodos.o \
prodos_read.o \
prodos_catalog.o \
prodos_dump.o \
prodos_volume_bitmap.o
prodos_volume_bitmap.o \
prodos_voldir.o
$(CC) -o prodos prodos.o \
prodos_read.o \
prodos_catalog.o \
prodos_dump.o \
prodos_volume_bitmap.o $(LFLAGS)
prodos_volume_bitmap.o \
prodos_voldir.o $(LFLAGS)
prodos.o: prodos.c prodos.h
$(CC) $(CFLAGS) -g -c prodos.c
@ -46,9 +48,11 @@ text_to_prodos.o: text_to_prodos.c
###
mkprodosfs: mkprodosfs.o prodos_read.o prodos_volume_bitmap.o
mkprodosfs: mkprodosfs.o prodos_read.o prodos_volume_bitmap.o \
prodos_voldir.o
$(CC) $(LFLAGS) -o mkprodosfs mkprodosfs.o \
prodos_read.o prodos_volume_bitmap.o
prodos_read.o prodos_volume_bitmap.o \
prodos_voldir.o
mkprodosfs.o: mkprodosfs.c prodos.h
$(CC) $(CFLAGS) -c mkprodosfs.c
@ -75,6 +79,12 @@ prodos_read.o: prodos_read.c prodos.h
###
prodos_voldir.o: prodos_voldir.c prodos.h
$(CC) $(CFLAGS) -c prodos_voldir.c
###
install:
cp prodos mkprodosfs prodoscat text_to_prodos $(INSTALL_LOC)

View File

@ -9,7 +9,11 @@
#include "prodos.h"
int debug=0;
int debug=1;
static int ones_lookup[8]={
0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF,
};
static void usage(char *binary,int help) {
@ -17,15 +21,12 @@ static void usage(char *binary,int help) {
printf("\tby Vince Weaver <vince@deater.net>\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] [-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-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("Usage:\t%s [-b size] [-i interleave] "
"[-s bootsector] device_name\n\n",binary);
printf("\t-b size : size of image, in 512B blocks\n");
printf("\t-i interleave : PRODOS (default) or DOS33\n");
printf("\t-s filename : bootsector\n");
printf("\t-n volume : volume name\n");
printf("\n\n");
}
exit(0);
@ -34,61 +35,52 @@ static void usage(char *binary,int help) {
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;
int max_ts_pairs=255;
int fd,dos_fd;
char device[BUFSIZ],dos_src[BUFSIZ];
unsigned char *vtoc_buffer=NULL,*sector_buffer=NULL;
int num_blocks=280;
int fd;
char device[BUFSIZ];
char *endptr;
int i,c,copy_dos=0;
int i,j,c;
int result;
unsigned char data_buffer[PRODOS_BYTES_PER_BLOCK];
struct voldir_t voldir;
char volname[PRODOS_VOLNAME_LEN];
int volname_len;
int interleave=PRODOS_INTERLEAVE_PRODOS;
int num_voldirs=4,num_bitmaps,num_bitmap_blocks,ones_to_write;
char boot_filename[30]="HELLO ";
strncpy(volname,"EMPTY",6);
volname_len=strlen(volname);
/* Parse Command Line Arguments */
while ((c = getopt (argc, argv,"t:s:b:d:f:m:n:hv"))!=-1) {
while ((c = getopt (argc, argv,"b:i:s:n: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':
sector_size=strtol(optarg,&endptr,10);
num_blocks=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);
break;
case 'f':
if (strlen(optarg)>30) {
fprintf(stderr,"Auto boot filename too long!\n");
exit(1);
case 'i':
if (!strncasecmp(optarg,"prodos",6)) {
interleave=PRODOS_INTERLEAVE_PRODOS;
}
memcpy(boot_filename,optarg,strlen(optarg));
for(i=strlen(optarg);i<30;i++) boot_filename[i]=' ';
// printf("Writing boot filename \"%s\"\n",boot_filename);
else if (!strncasecmp(optarg,"dos33",5)) {
interleave=PRODOS_INTERLEAVE_DOS33;
}
else {
fprintf(stderr,"Error! Unknown interleave: %s\n",optarg);
}
break;
case 's':
fprintf(stderr,"Error! -s not implemented yet!\n");
break;
case 'n':
memset(volname,0,sizeof(volname));
volname_len=strlen(optarg);
if (volname_len>PRODOS_VOLNAME_LEN) {
fprintf(stderr,"Volname: %s is too long!\n",optarg);
return -1;
}
memcpy(volname,optarg,volname_len);
break;
case 'v': usage(argv[0],0);
case 'h': usage(argv[0],1);
@ -107,41 +99,11 @@ int main(int argc, char **argv) {
/***********************/
/* 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");
if ((num_blocks<6) || (num_blocks>65536)) {
printf("Number of blocks must be >2 and <65536\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<vtoc_track) || (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) {
@ -150,205 +112,129 @@ int main(int argc, char **argv) {
goto end_of_program;
}
#if 0
/* zero out file */
for(i=0;i<num_tracks*num_sectors;i++) {
result=write(fd,vtoc_buffer,sector_size);
}
/**************************/
/* Calculating Paramaters */
/**************************/
if (volume_number>255) {
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;
}
catalog_sectors=max_files/7;
if (max_files%7) catalog_sectors++;
if (catalog_sectors>num_sectors-1) {
printf("Warning! num_files leads to too many sectors %d, max is %d\n",catalog_sectors,num_sectors-1);
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=VTOC_FREE_BITMAPS;i<sector_size;i+=4) {
vtoc_buffer[i]=0xff;
vtoc_buffer[i+1]=0xff;
if (num_sectors>16) {
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);
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,vtoc_buffer,sector_size);
result=write(fd,vtoc_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,vtoc_buffer,sector_size);
/* filename begins at offset 75 */
for(i=0;i<30;i++) {
vtoc_buffer[0x75+i]=boot_filename[i]|0x80;
}
lseek(fd,((1*num_sectors)+9)*sector_size,SEEK_SET);
result=write(fd,vtoc_buffer,sector_size);
/* if copying dos reserve tracks 1 and 2 as well */
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 0 */
/* No user data can be stored here as track=0 is used */
/* as a special-case end of file indicator */
for(i=0;i<num_sectors;i++) {
dos33_vtoc_reserve_sector(vtoc_buffer, 0, i);
}
/********************/
/* reserve the VTOC */
/********************/
dos33_vtoc_reserve_sector(vtoc_buffer, vtoc_track, 0);
/*****************/
/* Setup Catalog */
/* init voldir */
/*****************/
/* clear buffer */
memset(sector_buffer,0,sector_size);
memset(&voldir,0,sizeof(struct voldir_t));
/* Set catalog next pointers */
for(i=0;i<catalog_sectors;i++) {
/* point to next */
/* for first sector_size-1 walk backwards from T17S15 */
/* if more, allocate room on disk??? */
/* Max on 140k disk is 280 or so */
voldir.fd=fd;
voldir.interleave=interleave;
voldir.image_offset=0;
voldir.storage_type=PRODOS_FILE_VOLUME_HDR;
voldir.name_length=volname_len;
memcpy(voldir.volume_name,volname,volname_len);
voldir.total_blocks=num_blocks;
voldir.version=0;
voldir.min_version=0;
voldir.access=0xc3; // FIXME
voldir.entry_length=0x27;
voldir.entries_per_block=13;
current_sector=num_sectors-i-1;
voldir.bit_map_pointer=6;
if (i==catalog_sectors-1) {
/* last one, pointer is to 0,0 */
sector_buffer[1]=0;
sector_buffer[2]=0;
voldir.creation_time=0;
voldir.file_count=0;
voldir.next_block=3;
/******************/
/* clear out data */
/******************/
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
/* create image */
for(i=0;i<num_blocks;i++) {
result=prodos_write_block(&voldir,data_buffer,i);
if (result<0) {
fprintf(stderr,"Error writing!\n");
return -1;
}
}
/*********************************/
/* create the voldirs */
/*********************************/
for(i=0;i<num_voldirs;i++) {
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
/* prev */
if (i>0) {
data_buffer[0]=(PRODOS_VOLDIR_KEY_BLOCK+i-1)&0xff;
data_buffer[1]=(PRODOS_VOLDIR_KEY_BLOCK+i-1)>>8;
}
/* next */
if (i<num_voldirs-1) {
data_buffer[2]=(PRODOS_VOLDIR_KEY_BLOCK+i+1)&0xff;
data_buffer[3]=(PRODOS_VOLDIR_KEY_BLOCK+i+1)>>8;
}
result=prodos_write_block(&voldir,data_buffer,i+PRODOS_VOLDIR_KEY_BLOCK);
}
/*********************************/
/* create the bitmaps */
/*********************************/
num_bitmaps=num_blocks/8;
num_bitmap_blocks=1+((num_bitmaps-1)/512);
for(i=0;i<num_bitmap_blocks;i++) {
memset(data_buffer,0,PRODOS_BYTES_PER_BLOCK);
if (i*512*8>num_blocks) {
ones_to_write=512;
}
else {
printf("Writing $%02X,$%02X=%d,%d\n",
catalog_track,current_sector,
catalog_track,current_sector-1);
sector_buffer[1]=catalog_track;
sector_buffer[2]=current_sector-1;
ones_to_write=num_blocks%(512*8);
}
/* reserve */
dos33_vtoc_reserve_sector(vtoc_buffer,
catalog_track, current_sector);
if (debug) printf("Writing %d ones\n",ones_to_write);
lseek(fd,((catalog_track*num_sectors)+current_sector)*
sector_size,SEEK_SET);
result=write(fd,sector_buffer,sector_size);
if (result!=sector_size) {
fprintf(stderr,"Error writing catalog sector %d! (%s)\n",
current_sector,strerror(errno));
for(j=0;j<ones_to_write/8;j++) {
data_buffer[j]=0xff;
}
if (ones_to_write%8) {
data_buffer[j]=ones_lookup[ones_to_write%8];
}
result=prodos_write_block(&voldir,data_buffer,
PRODOS_VOLDIR_KEY_BLOCK+num_voldirs+i);
if (debug) printf("Wrote bitmap to block $%X\n",
PRODOS_VOLDIR_KEY_BLOCK+num_voldirs+i);
if (result<0) {
fprintf(stderr,"Error writing!\n");
return -1;
}
}
/**************************/
/* Write out VTOC to disk */
/**************************/
lseek(fd,((vtoc_track*num_sectors)+0)*sector_size,SEEK_SET);
/*********************************/
/* reserve all of the used space */
/*********************************/
result=write(fd,vtoc_buffer,sector_size);
if (result<0) {
fprintf(stderr,"Error writing VTOC (%s)!\n",strerror(errno));
prodos_voldir_reserve_block(&voldir,0); // boot sector
prodos_voldir_reserve_block(&voldir,1); // SOS boot sector
for(i=0;i<num_voldirs;i++) {
prodos_voldir_reserve_block(&voldir,
PRODOS_VOLDIR_KEY_BLOCK+i); // 2..5
}
for(i=0;i<num_bitmap_blocks;i++) {
prodos_voldir_reserve_block(&voldir,
PRODOS_VOLDIR_KEY_BLOCK+num_voldirs+i); // 6
}
#endif
/*********************************/
/* write out voldir */
/*********************************/
prodos_sync_voldir(&voldir);
close(fd);
end_of_program:
if (vtoc_buffer) free(vtoc_buffer);
if (sector_buffer) free(sector_buffer);
return 0;
}

View File

@ -14,60 +14,6 @@
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, int image_offset) {
int result;
unsigned char voldir_buffer[PRODOS_BYTES_PER_BLOCK];
voldir->interleave=interleave;
voldir->image_offset=image_offset;
/* read in VOLDIR KEY Block*/
voldir->fd=fd;
result=prodos_read_block(voldir,voldir_buffer,PRODOS_VOLDIR_KEY_BLOCK);
if (result<0) {
fprintf(stderr,"Error reading VOLDIR\n");
return -1;
}
voldir->fd=fd;
voldir->storage_type=(voldir_buffer[0x4]>>4)&0xf;
voldir->name_length=(voldir_buffer[0x4]&0xf);
if (voldir->storage_type!=0xf) {
fprintf(stderr,"ERROR! Expected storage type F\n");
}
memcpy(voldir->volume_name,&voldir_buffer[0x5],voldir->name_length);
voldir->volume_name[voldir->name_length]=0;
voldir->creation_time=(voldir_buffer[0x1c]<<16)|
(voldir_buffer[0x1d]<<24)|
(voldir_buffer[0x1e]<<0)|
(voldir_buffer[0x1f]<<8);
voldir->version=voldir_buffer[0x20];
voldir->min_version=voldir_buffer[0x21];
voldir->access=voldir_buffer[0x22];
voldir->entry_length=voldir_buffer[0x23];
if (voldir->entry_length!=PRODOS_FILE_DESC_LEN) {
printf("Error! Unexpected desc len %d\n",
voldir->entry_length);
}
voldir->entries_per_block=voldir_buffer[0x24];
voldir->file_count=voldir_buffer[0x25]|(voldir_buffer[0x26]<<8);
voldir->bit_map_pointer=voldir_buffer[0x27]|(voldir_buffer[0x28]<<8);
voldir->total_blocks=voldir_buffer[0x29]|(voldir_buffer[0x2A]<<8);
voldir->next_block=voldir_buffer[0x2]|(voldir_buffer[0x3]<<8);
return 0;
}
/* Given filename, return voldir/offset */
static int prodos_lookup_file(struct voldir_t *voldir,
@ -480,6 +426,10 @@ static int prodos_add_file(struct voldir_t *voldir,
/* write back existing voldir entry */
result=prodos_write_block(voldir,data_buffer,inode>>8);
/* update file count */
voldir->file_count++;
prodos_sync_voldir(voldir);
return 0;
}
@ -900,66 +850,6 @@ 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) {
@ -1387,7 +1277,7 @@ int main(int argc, char **argv) {
goto exit_and_close;
}
change_volume_name(&voldir,argv[optind]);
prodos_change_volume_name(&voldir,argv[optind]);
break;

View File

@ -1,9 +1,10 @@
/* 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 BLOCKS_PER_TRACK 0x8
#define PRODOS_BYTES_PER_BLOCK 0x200
#define PRODOS_VOLNAME_LEN 15
#define PRODOS_FILENAME_LEN 15
#define PRODOS_INTERLEAVE_PRODOS 0x0
#define PRODOS_INTERLEAVE_DOS33 0x1
@ -86,3 +87,9 @@ 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);
/* prodos_voldir.c */
int prodos_sync_voldir(struct voldir_t *voldir);
int prodos_change_volume_name(struct voldir_t *voldir, char *volname);
int prodos_read_voldir(int fd, struct voldir_t *voldir,
int interleave, int image_offset);

View File

@ -0,0 +1,131 @@
#include <stdio.h>
#include <stdlib.h> /* exit() */
#include <string.h> /* strncpy() */
#include <sys/stat.h> /* struct stat */
#include <fcntl.h> /* O_RDONLY */
#include <unistd.h> /* lseek() */
#include <ctype.h> /* toupper() */
#include <errno.h>
#include "version.h"
#include "prodos.h"
extern int debug;
/* Read volume directory into a buffer */
int prodos_read_voldir(int fd, struct voldir_t *voldir,
int interleave, int image_offset) {
int result;
unsigned char voldir_buffer[PRODOS_BYTES_PER_BLOCK];
voldir->interleave=interleave;
voldir->image_offset=image_offset;
/* read in VOLDIR KEY Block*/
voldir->fd=fd;
result=prodos_read_block(voldir,voldir_buffer,PRODOS_VOLDIR_KEY_BLOCK);
if (result<0) {
fprintf(stderr,"Error reading VOLDIR\n");
return -1;
}
voldir->fd=fd;
voldir->storage_type=(voldir_buffer[0x4]>>4)&0xf;
voldir->name_length=(voldir_buffer[0x4]&0xf);
if (voldir->storage_type!=0xf) {
fprintf(stderr,"ERROR! Expected storage type F\n");
}
memcpy(voldir->volume_name,&voldir_buffer[0x5],voldir->name_length);
voldir->volume_name[voldir->name_length]=0;
voldir->creation_time=(voldir_buffer[0x1c]<<16)|
(voldir_buffer[0x1d]<<24)|
(voldir_buffer[0x1e]<<0)|
(voldir_buffer[0x1f]<<8);
voldir->version=voldir_buffer[0x20];
voldir->min_version=voldir_buffer[0x21];
voldir->access=voldir_buffer[0x22];
voldir->entry_length=voldir_buffer[0x23];
if (voldir->entry_length!=PRODOS_FILE_DESC_LEN) {
printf("Error! Unexpected desc len %d\n",
voldir->entry_length);
}
voldir->entries_per_block=voldir_buffer[0x24];
voldir->file_count=voldir_buffer[0x25]|(voldir_buffer[0x26]<<8);
voldir->bit_map_pointer=voldir_buffer[0x27]|(voldir_buffer[0x28]<<8);
voldir->total_blocks=voldir_buffer[0x29]|(voldir_buffer[0x2A]<<8);
voldir->next_block=voldir_buffer[0x2]|(voldir_buffer[0x3]<<8);
return 0;
}
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;
}
int prodos_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;
}