prodos: LOAD of a seed file works now

the DOS33 interleave support was horribly broken
This commit is contained in:
Vince Weaver 2021-08-01 19:11:09 -04:00
parent 907146f43b
commit 0cba4da691
4 changed files with 145 additions and 28 deletions

View File

@ -1,5 +1,7 @@
include ../../Makefile.inc
CFLAGS := $(CFLAGS) -g
all: prodos mkprodosfs
###

View File

@ -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);

View File

@ -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;
file<voldir->entries_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) {

View File

@ -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 (result<PRODOS_BYTES_PER_BLOCK) {
fprintf(stderr,"Error reading block %d\n",blocknum);
fprintf(stderr,"Error reading block $%X\n",blocknum);
return -1;
}
}
else if (voldir->interleave==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 (result<PRODOS_BYTES_PER_BLOCK/2) {
fprintf(stderr,"Error reading block %d\n",blocknum);
fprintf(stderr,"Error reading block $%X (%X)\n",
blocknum,((track<<4)+sector1));
return -1;
}
lseek(voldir->fd,(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<PRODOS_BYTES_PER_BLOCK/2) {
fprintf(stderr,"Error reading block %d\n",blocknum);
fprintf(stderr,"Error reading block $%X (%X)\n",
blocknum,((track<<4)+sector2));
return -1;
}