mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-12-27 02:31:00 +00:00
prodos-utils: this is probably a mistake
just want enough to get things onto/offof a Logo II disk
This commit is contained in:
parent
2e8b0a20ce
commit
46fb87bf64
52
utils/prodos-utils/Makefile
Normal file
52
utils/prodos-utils/Makefile
Normal file
@ -0,0 +1,52 @@
|
||||
include ../../Makefile.inc
|
||||
|
||||
all: prodos mkprodosfs
|
||||
|
||||
###
|
||||
|
||||
prodos: prodos.o \
|
||||
prodos_catalog.o \
|
||||
prodos_dump.o \
|
||||
prodos_volume_bitmap.o
|
||||
$(CC) -o prodos prodos.o \
|
||||
prodos_catalog.o \
|
||||
prodos_dump.o \
|
||||
prodos_volume_bitmap.o $(LFLAGS)
|
||||
|
||||
prodos.o: prodos.c prodos.h
|
||||
$(CC) $(CFLAGS) -g -c prodos.c
|
||||
|
||||
|
||||
###
|
||||
|
||||
mkprodosfs: mkprodosfs.o prodos_volume_bitmap.o
|
||||
$(CC) $(LFLAGS) -o mkprodosfs mkprodosfs.o \
|
||||
prodos_volume_bitmap.o
|
||||
|
||||
mkprodosfs.o: mkprodosfs.c prodos.h
|
||||
$(CC) $(CFLAGS) -c mkprodosfs.c
|
||||
|
||||
###
|
||||
|
||||
prodos_volume_bitmap.o: prodos_volume_bitmap.c prodos.h
|
||||
$(CC) $(CFLAGS) -c prodos_volume_bitmap.c
|
||||
|
||||
###
|
||||
|
||||
prodos_catalog.o: prodos_catalog.c prodos.h
|
||||
$(CC) $(CFLAGS) -c prodos_catalog.c
|
||||
|
||||
###
|
||||
|
||||
prodos_dump.o: prodos_dump.c prodos.h
|
||||
$(CC) $(CFLAGS) -c prodos_dump.c
|
||||
|
||||
###
|
||||
|
||||
|
||||
install:
|
||||
cp prodos prodos_raw mkprodosfs make_b prodos_text2ascii char2hex $(INSTALL_LOC)
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o prodos prodos_raw mkprodosfs make_b prodos_text2ascii char2hex
|
||||
cd tests && make clean
|
10
utils/prodos-utils/README
Normal file
10
utils/prodos-utils/README
Normal file
@ -0,0 +1,10 @@
|
||||
=============
|
||||
prodos-utils
|
||||
=============
|
||||
|
||||
Tools for manipulating an Apple II 140k prodos filesystem.
|
||||
|
||||
+ prodos : a tool for manipulating prodos .po / .dsk images
|
||||
|
||||
+ mkprodosfs: create an Apple ][ ProDOS filesystems
|
||||
|
351
utils/prodos-utils/mkprodosfs.c
Normal file
351
utils/prodos-utils/mkprodosfs.c
Normal file
@ -0,0 +1,351 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* strncpy() */
|
||||
#include <fcntl.h> /* open() */
|
||||
#include <unistd.h> /* close() */
|
||||
#include <stdlib.h> /* strtol() */
|
||||
#include <errno.h>
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "prodos.h"
|
||||
|
||||
static void usage(char *binary,int help) {
|
||||
|
||||
printf("\n%s - version %s\n",binary,VERSION);
|
||||
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("\n\n");
|
||||
}
|
||||
exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
char *endptr;
|
||||
int i,c,copy_dos=0;
|
||||
int result;
|
||||
|
||||
char boot_filename[30]="HELLO ";
|
||||
|
||||
/* Parse Command Line Arguments */
|
||||
|
||||
while ((c = getopt (argc, argv,"t:s:b:d:f:m: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);
|
||||
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);
|
||||
}
|
||||
memcpy(boot_filename,optarg,strlen(optarg));
|
||||
for(i=strlen(optarg);i<30;i++) boot_filename[i]=' ';
|
||||
// printf("Writing boot filename \"%s\"\n",boot_filename);
|
||||
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-1);
|
||||
|
||||
/***********************/
|
||||
/* Sanity check values */
|
||||
/***********************/
|
||||
|
||||
/* 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");
|
||||
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) {
|
||||
fprintf(stderr,"Error opening %s (%s)\n",
|
||||
device,strerror(errno));
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
/*****************/
|
||||
|
||||
/* clear buffer */
|
||||
memset(sector_buffer,0,sector_size);
|
||||
|
||||
/* 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 */
|
||||
|
||||
current_sector=num_sectors-i-1;
|
||||
|
||||
if (i==catalog_sectors-1) {
|
||||
/* last one, pointer is to 0,0 */
|
||||
sector_buffer[1]=0;
|
||||
sector_buffer[2]=0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* reserve */
|
||||
dos33_vtoc_reserve_sector(vtoc_buffer,
|
||||
catalog_track, current_sector);
|
||||
|
||||
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));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* Write out VTOC to disk */
|
||||
/**************************/
|
||||
lseek(fd,((vtoc_track*num_sectors)+0)*sector_size,SEEK_SET);
|
||||
|
||||
result=write(fd,vtoc_buffer,sector_size);
|
||||
if (result<0) {
|
||||
fprintf(stderr,"Error writing VTOC (%s)!\n",strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
|
||||
close(fd);
|
||||
|
||||
end_of_program:
|
||||
if (vtoc_buffer) free(vtoc_buffer);
|
||||
if (sector_buffer) free(sector_buffer);
|
||||
|
||||
return 0;
|
||||
}
|
1303
utils/prodos-utils/prodos.c
Normal file
1303
utils/prodos-utils/prodos.c
Normal file
File diff suppressed because it is too large
Load Diff
76
utils/prodos-utils/prodos.h
Normal file
76
utils/prodos-utils/prodos.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* 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 BYTES_PER_BLOCK 0x200
|
||||
|
||||
#define VOLDIR_TRACK 0x0
|
||||
#define VOLDIR_BLOCK 0x200
|
||||
|
||||
/* 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)*BLOCKS_PER_TRACK)+(__sector))*BYTES_PER_BLOCK)
|
||||
|
||||
|
||||
#define DOS33_FILE_NORMAL 0
|
||||
#define DOS33_FILE_DELETED 1
|
||||
|
||||
/* prodos_volume_bitmap.c */
|
||||
int dos33_vtoc_free_space(unsigned char *vtoc);
|
||||
void dos33_vtoc_free_sector(unsigned char *vtoc, int track, int sector);
|
||||
void dos33_vtoc_reserve_sector(unsigned char *vtoc, int track, int sector);
|
||||
void dos33_vtoc_dump_bitmap(unsigned char *vtoc, int num_tracks);
|
||||
int dos33_vtoc_find_free_sector(unsigned char *vtoc,
|
||||
int *found_track, int *found_sector);
|
||||
|
||||
/* prodos_catalog.c */
|
||||
unsigned char dos33_char_to_type(char type, int lock);
|
||||
void dos33_catalog(int dos_fd, unsigned char *vtoc);
|
||||
char *dos33_filename_to_ascii(char *dest,unsigned char *src,int len);
|
||||
unsigned char dos33_file_type(int value);
|
||||
|
||||
/* prodos_dump.c */
|
||||
int dos33_dump(unsigned char *vtoc, int fd);
|
||||
int dos33_showfree(unsigned char *vtoc, int fd);
|
212
utils/prodos-utils/prodos_catalog.c
Normal file
212
utils/prodos-utils/prodos_catalog.c
Normal file
@ -0,0 +1,212 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "prodos.h"
|
||||
|
||||
static int debug=0;
|
||||
|
||||
unsigned char dos33_file_type(int value) {
|
||||
|
||||
unsigned char result;
|
||||
|
||||
switch(value&0x7f) {
|
||||
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(char *dest,unsigned char *src,int len) {
|
||||
|
||||
int i=0,last_nonspace=0;
|
||||
|
||||
for(i=0;i<len;i++) if (src[i]!=0xA0) last_nonspace=i;
|
||||
|
||||
for(i=0;i<last_nonspace+1;i++) {
|
||||
dest[i]=src[i]^0x80; /* toggle top bit */
|
||||
}
|
||||
|
||||
dest[i]='\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Get a T/S value from a Catalog Sector */
|
||||
static int dos33_get_catalog_ts(unsigned char *voldir) {
|
||||
|
||||
return TS_TO_INT(voldir[VTOC_CATALOG_T],voldir[VTOC_CATALOG_S]);
|
||||
}
|
||||
|
||||
/* returns the next valid catalog entry */
|
||||
/* after the one passed in */
|
||||
static int dos33_find_next_file(int fd,int catalog_tsf,unsigned char *voldir) {
|
||||
|
||||
int catalog_track,catalog_sector,catalog_file;
|
||||
int file_track,i;
|
||||
int result;
|
||||
unsigned char sector_buffer[BYTES_PER_BLOCK];
|
||||
|
||||
catalog_file=catalog_tsf>>16;
|
||||
catalog_track=(catalog_tsf>>8)&0xff;
|
||||
catalog_sector=(catalog_tsf&0xff);
|
||||
|
||||
if (debug) {
|
||||
fprintf(stderr,"CATALOG FIND NEXT, "
|
||||
"CURRENT FILE=%X TRACK=%X SECTOR=%X\n",
|
||||
catalog_file,catalog_track,catalog_sector);
|
||||
}
|
||||
|
||||
catalog_loop:
|
||||
|
||||
/* Read in Catalog Sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
result=read(fd,sector_buffer,BYTES_PER_BLOCK);
|
||||
if (result<0) {
|
||||
fprintf(stderr,"Error on I/O %s\n",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
i=catalog_file;
|
||||
while(i<7) {
|
||||
|
||||
file_track=sector_buffer[CATALOG_FILE_LIST+
|
||||
(i*CATALOG_ENTRY_SIZE)];
|
||||
/* 0xff means file deleted */
|
||||
/* 0x0 means empty */
|
||||
if (debug) {
|
||||
if (file_track==0xff) fprintf(stderr,"\tFILE %d DELETED\n",i);
|
||||
if (file_track==0x00) fprintf(stderr,"\tFILE %d UNALLOCATED\n",i);
|
||||
}
|
||||
|
||||
if ((file_track!=0xff) && (file_track!=0x0)) {
|
||||
if (debug) fprintf(stderr,"\tFOUND FILE %X TRACK $%X SECTOR $%X\n",i,catalog_track,catalog_sector);
|
||||
return ((i<<16)+(catalog_track<<8)+catalog_sector);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
catalog_track=sector_buffer[CATALOG_NEXT_T];
|
||||
catalog_sector=sector_buffer[CATALOG_NEXT_S];
|
||||
|
||||
if (debug) fprintf(stderr,"\tTRYING NEXT SECTOR T=$%X S=$%X\n",
|
||||
catalog_track,catalog_sector);
|
||||
|
||||
/* FIXME: this wouldn't happen on 140k disks */
|
||||
/* but who knows if you're doing something fancy? */
|
||||
if ((catalog_track<0) || (catalog_track>40)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (catalog_sector!=0) {
|
||||
catalog_file=0;
|
||||
goto catalog_loop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dos33_print_file_info(int fd,int catalog_tsf) {
|
||||
|
||||
int catalog_track,catalog_sector,catalog_file,i;
|
||||
char temp_string[BUFSIZ];
|
||||
int result;
|
||||
unsigned char sector_buffer[BYTES_PER_BLOCK];
|
||||
|
||||
catalog_file=catalog_tsf>>16;
|
||||
catalog_track=(catalog_tsf>>8)&0xff;
|
||||
catalog_sector=(catalog_tsf&0xff);
|
||||
|
||||
if (debug) fprintf(stderr,"CATALOG FILE=%X TRACK=%X SECTOR=%X\n",
|
||||
catalog_file,catalog_track,catalog_sector);
|
||||
|
||||
/* Read in Catalog Sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
result=read(fd,sector_buffer,BYTES_PER_BLOCK);
|
||||
|
||||
if (sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f) {
|
||||
printf("*");
|
||||
}
|
||||
else {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("%c",dos33_file_type(sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]));
|
||||
printf(" ");
|
||||
printf("%.3i ",sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_SIZE_L)]+
|
||||
(sector_buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_SIZE_H)]<<8));
|
||||
|
||||
dos33_filename_to_ascii(temp_string,sector_buffer+(CATALOG_FILE_LIST+
|
||||
(catalog_file*CATALOG_ENTRY_SIZE+FILE_NAME)),30);
|
||||
|
||||
for(i=0;i<strlen(temp_string);i++) {
|
||||
if (temp_string[i]<0x20) {
|
||||
printf("^%c",temp_string[i]+0x40);
|
||||
}
|
||||
else {
|
||||
printf("%c",temp_string[i]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (result<0) fprintf(stderr,"Error on I/O\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dos33_catalog(int dos_fd, unsigned char *voldir) {
|
||||
|
||||
int catalog_entry;
|
||||
|
||||
/* get first catalog */
|
||||
catalog_entry=dos33_get_catalog_ts(voldir);
|
||||
|
||||
printf("\nDISK VOLUME %i\n\n",voldir[VTOC_DISK_VOLUME]);
|
||||
while(catalog_entry>0) {
|
||||
catalog_entry=dos33_find_next_file(dos_fd,catalog_entry,voldir);
|
||||
if (debug) fprintf(stderr,"CATALOG entry=$%X\n",catalog_entry);
|
||||
if (catalog_entry>0) {
|
||||
dos33_print_file_info(dos_fd,catalog_entry);
|
||||
/* why 1<<16 ? */
|
||||
catalog_entry+=(1<<16);
|
||||
/* dos33_find_next_file() handles wrapping issues */
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
349
utils/prodos-utils/prodos_dump.c
Normal file
349
utils/prodos-utils/prodos_dump.c
Normal file
@ -0,0 +1,349 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "prodos.h"
|
||||
|
||||
|
||||
static int dump_sector(unsigned char *sector_buffer) {
|
||||
|
||||
int i,j;
|
||||
|
||||
for(i=0;i<16;i++) {
|
||||
printf("$%02X : ",i*16);
|
||||
for(j=0;j<16;j++) {
|
||||
printf("%02X ",sector_buffer[i*16+j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_voldir(unsigned char *voldir) {
|
||||
|
||||
int num_tracks,catalog_t,catalog_s,ts_total;
|
||||
|
||||
printf("\nVTOC Sector:\n");
|
||||
dump_sector(voldir);
|
||||
|
||||
printf("\n\n");
|
||||
printf("VTOC INFORMATION:\n");
|
||||
catalog_t=voldir[VTOC_CATALOG_T];
|
||||
catalog_s=voldir[VTOC_CATALOG_S];
|
||||
printf("\tFirst Catalog = %02X/%02X\n",catalog_t,catalog_s);
|
||||
printf("\tDOS RELEASE = 3.%i\n",voldir[VTOC_DOS_RELEASE]);
|
||||
printf("\tDISK VOLUME = %i\n",voldir[VTOC_DISK_VOLUME]);
|
||||
ts_total=voldir[VTOC_MAX_TS_PAIRS];
|
||||
printf("\tT/S pairs that will fit in T/S List = %i\n",ts_total);
|
||||
|
||||
printf("\tLast track where sectors were allocated = $%02X\n",
|
||||
voldir[VTOC_LAST_ALLOC_T]);
|
||||
printf("\tDirection of track allocation = %i\n",
|
||||
voldir[VTOC_ALLOC_DIRECT]);
|
||||
|
||||
num_tracks=voldir[VTOC_NUM_TRACKS];
|
||||
printf("\tNumber of tracks per disk = %i\n",num_tracks);
|
||||
printf("\tNumber of sectors per track = %i\n",
|
||||
voldir[VTOC_S_PER_TRACK]);
|
||||
printf("\tNumber of bytes per sector = %i\n",
|
||||
(voldir[VTOC_BYTES_PER_SH]<<8)+
|
||||
voldir[VTOC_BYTES_PER_SL]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int dos33_dump(unsigned char *voldir, int fd) {
|
||||
|
||||
int num_tracks,catalog_t,catalog_s,file,ts_t,ts_s,ts_total;
|
||||
int track,sector;
|
||||
int i;
|
||||
int deleted=0;
|
||||
char temp_string[BUFSIZ];
|
||||
unsigned char tslist[BYTES_PER_BLOCK];
|
||||
unsigned char catalog_buffer[BYTES_PER_BLOCK];
|
||||
unsigned char data[BYTES_PER_BLOCK];
|
||||
int result;
|
||||
|
||||
/* Read Track 1 Sector 9 */
|
||||
lseek(fd,DISK_OFFSET(1,9),SEEK_SET);
|
||||
result=read(fd,data,BYTES_PER_BLOCK);
|
||||
|
||||
printf("Finding name of startup file, Track 1 Sector 9 offset $75\n");
|
||||
|
||||
if (data[0x75]!=0) {
|
||||
printf("Startup Filename: ");
|
||||
for(i=0;i<30;i++) {
|
||||
printf("%c",data[0x75+i]&0x7f);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
dump_voldir(voldir);
|
||||
|
||||
catalog_t=voldir[VTOC_CATALOG_T];
|
||||
catalog_s=voldir[VTOC_CATALOG_S];
|
||||
ts_total=voldir[VTOC_MAX_TS_PAIRS];
|
||||
num_tracks=voldir[VTOC_NUM_TRACKS];
|
||||
|
||||
dos33_vtoc_dump_bitmap(voldir,num_tracks);
|
||||
|
||||
repeat_catalog:
|
||||
|
||||
printf("\nCatalog Sector $%02X/$%02x\n",catalog_t,catalog_s);
|
||||
lseek(fd,DISK_OFFSET(catalog_t,catalog_s),SEEK_SET);
|
||||
result=read(fd,catalog_buffer,BYTES_PER_BLOCK);
|
||||
|
||||
printf("\tNext track/sector $%02X/$%02X (found at offsets $%02X/$%02X\n",
|
||||
catalog_buffer[CATALOG_NEXT_T],catalog_buffer[CATALOG_NEXT_S],
|
||||
CATALOG_NEXT_T,CATALOG_NEXT_S);
|
||||
|
||||
dump_sector(catalog_buffer);
|
||||
|
||||
for(file=0;file<7;file++) {
|
||||
printf("\n\n");
|
||||
|
||||
ts_t=catalog_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_TS_LIST_T))];
|
||||
ts_s=catalog_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_TS_LIST_S))];
|
||||
|
||||
printf("%i+$%02X/$%02X - ",file,catalog_t,catalog_s);
|
||||
deleted=0;
|
||||
|
||||
if (ts_t==0xff) {
|
||||
printf("**DELETED** ");
|
||||
deleted=1;
|
||||
ts_t=catalog_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_NAME+0x1e))];
|
||||
}
|
||||
|
||||
if (ts_t==0x00) {
|
||||
printf("UNUSED!\n");
|
||||
goto continue_dump;
|
||||
}
|
||||
|
||||
dos33_filename_to_ascii(temp_string,
|
||||
catalog_buffer+(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_NAME)),30);
|
||||
|
||||
for(i=0;i<strlen(temp_string);i++) {
|
||||
if (temp_string[i]<0x20) {
|
||||
printf("^%c",temp_string[i]+0x40);
|
||||
}
|
||||
else {
|
||||
printf("%c",temp_string[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
printf("\tLocked = %s\n",
|
||||
catalog_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f?
|
||||
"YES":"NO");
|
||||
printf("\tType = %c\n",
|
||||
dos33_file_type(catalog_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE]));
|
||||
printf("\tSize in sectors = %i\n",
|
||||
catalog_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_SIZE_L)]+
|
||||
(catalog_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_SIZE_H)]<<8));
|
||||
|
||||
repeat_tsl:
|
||||
printf("\tT/S List $%02X/$%02X:\n",ts_t,ts_s);
|
||||
if (deleted) goto continue_dump;
|
||||
lseek(fd,DISK_OFFSET(ts_t,ts_s),SEEK_SET);
|
||||
result=read(fd,&tslist,BYTES_PER_BLOCK);
|
||||
|
||||
for(i=0;i<ts_total;i++) {
|
||||
track=tslist[TSL_LIST+(i*TSL_ENTRY_SIZE)];
|
||||
sector=tslist[TSL_LIST+(i*TSL_ENTRY_SIZE)+1];
|
||||
if ((track==0) && (sector==0)) printf(".");
|
||||
else printf("\n\t\t%02X/%02X",track,sector);
|
||||
}
|
||||
ts_t=tslist[TSL_NEXT_TRACK];
|
||||
ts_s=tslist[TSL_NEXT_SECTOR];
|
||||
|
||||
if (!((ts_s==0) && (ts_t==0))) goto repeat_tsl;
|
||||
continue_dump:;
|
||||
}
|
||||
|
||||
catalog_t=catalog_buffer[CATALOG_NEXT_T];
|
||||
catalog_s=catalog_buffer[CATALOG_NEXT_S];
|
||||
|
||||
if (catalog_s!=0) {
|
||||
file=0;
|
||||
goto repeat_catalog;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (result<0) fprintf(stderr,"Error on I/O\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dos33_showfree(unsigned char *voldir, int fd) {
|
||||
|
||||
int num_tracks,catalog_t,catalog_s,file,ts_t,ts_s,ts_total;
|
||||
int track,sector;
|
||||
int i,j;
|
||||
int deleted=0;
|
||||
char temp_string[BUFSIZ];
|
||||
unsigned char tslist[BYTES_PER_BLOCK];
|
||||
unsigned char catalog_buffer[BYTES_PER_BLOCK];
|
||||
int result;
|
||||
|
||||
int sectors_per_track;
|
||||
int catalog_used;
|
||||
int next_letter='a';
|
||||
struct file_key_type {
|
||||
int ch;
|
||||
char *filename;
|
||||
} file_key[100];
|
||||
int num_files=0;
|
||||
|
||||
|
||||
unsigned char usage[35][16];
|
||||
|
||||
for(i=0;i<35;i++) for(j=0;j<16;j++) usage[i][j]=0;
|
||||
|
||||
dump_voldir(voldir);
|
||||
|
||||
catalog_t=voldir[VTOC_CATALOG_T];
|
||||
catalog_s=voldir[VTOC_CATALOG_S];
|
||||
ts_total=voldir[VTOC_MAX_TS_PAIRS];
|
||||
num_tracks=voldir[VTOC_NUM_TRACKS];
|
||||
sectors_per_track=voldir[VTOC_S_PER_TRACK];
|
||||
|
||||
dos33_vtoc_dump_bitmap(voldir,num_tracks);
|
||||
|
||||
/* Reserve DOS */
|
||||
for(i=0;i<3;i++) for(j=0;j<16;j++) usage[i][j]='$';
|
||||
|
||||
/* Reserve CATALOG (not all used?) */
|
||||
i=0x11;
|
||||
for(j=0;j<16;j++) usage[i][j]='#';
|
||||
|
||||
|
||||
repeat_catalog:
|
||||
|
||||
catalog_used=0;
|
||||
|
||||
// printf("\nCatalog Sector $%02X/$%02x\n",catalog_t,catalog_s);
|
||||
lseek(fd,DISK_OFFSET(catalog_t,catalog_s),SEEK_SET);
|
||||
result=read(fd,catalog_buffer,BYTES_PER_BLOCK);
|
||||
|
||||
|
||||
// dump_sector();
|
||||
|
||||
for(file=0;file<7;file++) {
|
||||
// printf("\n\n");
|
||||
|
||||
ts_t=catalog_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_TS_LIST_T))];
|
||||
ts_s=catalog_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_TS_LIST_S))];
|
||||
|
||||
// printf("%i+$%02X/$%02X - ",file,catalog_t,catalog_s);
|
||||
deleted=0;
|
||||
|
||||
if (ts_t==0xff) {
|
||||
printf("**DELETED** ");
|
||||
deleted=1;
|
||||
ts_t=catalog_buffer[(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_NAME+0x1e))];
|
||||
}
|
||||
|
||||
if (ts_t==0x00) {
|
||||
// printf("UNUSED!\n");
|
||||
goto continue_dump;
|
||||
}
|
||||
|
||||
dos33_filename_to_ascii(temp_string,
|
||||
catalog_buffer+(CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_NAME)),
|
||||
30);
|
||||
|
||||
for(i=0;i<strlen(temp_string);i++) {
|
||||
if (temp_string[i]<0x20) {
|
||||
printf("^%c",temp_string[i]+0x40);
|
||||
}
|
||||
else {
|
||||
printf("%c",temp_string[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
// printf("\tLocked = %s\n",
|
||||
// sector_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f?
|
||||
// "YES":"NO");
|
||||
// printf("\tType = %c\n",
|
||||
// dos33_file_type(sector_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE)+FILE_TYPE]));
|
||||
// printf("\tSize in sectors = %i\n",
|
||||
// sector_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_SIZE_L)]+
|
||||
// (sector_buffer[CATALOG_FILE_LIST+(file*CATALOG_ENTRY_SIZE+FILE_SIZE_H)]<<8));
|
||||
|
||||
if (!deleted) {
|
||||
catalog_used++;
|
||||
usage[catalog_t][catalog_s]='@';
|
||||
}
|
||||
|
||||
repeat_tsl:
|
||||
// printf("\tT/S List $%02X/$%02X:\n",ts_t,ts_s);
|
||||
if (deleted) goto continue_dump;
|
||||
|
||||
usage[ts_t][ts_s]=next_letter;
|
||||
file_key[num_files].ch=next_letter;
|
||||
file_key[num_files].filename=strdup(temp_string);
|
||||
|
||||
num_files++;
|
||||
|
||||
|
||||
lseek(fd,DISK_OFFSET(ts_t,ts_s),SEEK_SET);
|
||||
result=read(fd,&tslist,BYTES_PER_BLOCK);
|
||||
|
||||
for(i=0;i<ts_total;i++) {
|
||||
track=tslist[TSL_LIST+(i*TSL_ENTRY_SIZE)];
|
||||
sector=tslist[TSL_LIST+(i*TSL_ENTRY_SIZE)+1];
|
||||
if ((track==0) && (sector==0)) {
|
||||
//printf(".");
|
||||
}
|
||||
else {
|
||||
// printf("\n\t\t%02X/%02X",track,sector);
|
||||
usage[track][sector]=toupper(next_letter);
|
||||
}
|
||||
}
|
||||
ts_t=tslist[TSL_NEXT_TRACK];
|
||||
ts_s=tslist[TSL_NEXT_SECTOR];
|
||||
|
||||
if (!((ts_s==0) && (ts_t==0))) goto repeat_tsl;
|
||||
continue_dump:;
|
||||
|
||||
next_letter++;
|
||||
}
|
||||
|
||||
catalog_t=catalog_buffer[CATALOG_NEXT_T];
|
||||
catalog_s=catalog_buffer[CATALOG_NEXT_S];
|
||||
|
||||
if (catalog_s!=0) {
|
||||
file=0;
|
||||
goto repeat_catalog;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (result<0) fprintf(stderr,"Error on I/O\n");
|
||||
|
||||
printf("\nDetailed sector bitmap:\n\n");
|
||||
printf("\t 1111111111111111222\n");
|
||||
printf("\t0123456789ABCDEF0123456789ABCDEF012\n");
|
||||
|
||||
for(j=0;j<sectors_per_track;j++) {
|
||||
printf("$%01X:\t",j);
|
||||
for(i=0;i<num_tracks;i++) {
|
||||
if (usage[i][j]==0) printf(".");
|
||||
else printf("%c",usage[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
printf("Key: $=DOS, @=catalog used, #=catalog reserved, .=free\n\n");
|
||||
for(i=0;i<num_files;i++) {
|
||||
printf("\t%c %s\n",file_key[i].ch,file_key[i].filename);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
206
utils/prodos-utils/prodos_volume_bitmap.c
Normal file
206
utils/prodos-utils/prodos_volume_bitmap.c
Normal file
@ -0,0 +1,206 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "prodos.h"
|
||||
|
||||
/* FIXME: this code assumes that we have 16 sectors pretty much everywhere */
|
||||
|
||||
|
||||
static 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,
|
||||
};
|
||||
|
||||
/* could be replaced by "find leading 1" instruction */
|
||||
/* if available */
|
||||
static int find_first_one(unsigned char byte) {
|
||||
|
||||
int i=0;
|
||||
|
||||
if (byte==0) return -1;
|
||||
|
||||
while((byte & (0x1<<i))==0) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* Return how many bytes free in the filesystem */
|
||||
/* by reading the VTOC_FREE_BITMAP */
|
||||
int dos33_vtoc_free_space(unsigned char *vtoc) {
|
||||
|
||||
unsigned char bitmap[4];
|
||||
int i,sectors_free=0;
|
||||
|
||||
for(i=0;i<TRACKS_PER_DISK;i++) {
|
||||
bitmap[0]=vtoc[VTOC_FREE_BITMAPS+(i*4)];
|
||||
bitmap[1]=vtoc[VTOC_FREE_BITMAPS+(i*4)+1];
|
||||
|
||||
sectors_free+=ones_lookup[bitmap[0]&0xf];
|
||||
sectors_free+=ones_lookup[(bitmap[0]>>4)&0xf];
|
||||
sectors_free+=ones_lookup[bitmap[1]&0xf];
|
||||
sectors_free+=ones_lookup[(bitmap[1]>>4)&0xf];
|
||||
}
|
||||
|
||||
return sectors_free*BYTES_PER_BLOCK;
|
||||
}
|
||||
|
||||
/* free a sector from the sector bitmap */
|
||||
void dos33_vtoc_free_sector(unsigned char *vtoc, int track, int sector) {
|
||||
|
||||
/* each bitmap is 32 bits. With 16-sector tracks only first 16 used */
|
||||
/* 1 indicates free, 0 indicates used */
|
||||
if (sector<8) {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+1]|=(0x1<<sector);
|
||||
}
|
||||
else if (sector<16) {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+0]|=(0x1<<(sector-8));
|
||||
}
|
||||
else if (sector<24) {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+3]|=(0x1<<(sector-16));
|
||||
}
|
||||
else if (sector<32) {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+2]|=(0x1<<(sector-24));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"Error vtoc_free_sector! sector too big %d\n",sector);
|
||||
}
|
||||
}
|
||||
|
||||
/* reserve a sector in the sector bitmap */
|
||||
void dos33_vtoc_reserve_sector(unsigned char *vtoc, int track, int sector) {
|
||||
|
||||
/* each bitmap is 32 bits. With 16-sector tracks only first 16 used */
|
||||
/* 1 indicates free, 0 indicates used */
|
||||
if (sector<8) {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+1]&=~(0x1<<sector);
|
||||
}
|
||||
else if (sector<16) {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+0]&=~(0x1<<(sector-8));
|
||||
}
|
||||
else if (sector<24) {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+3]&=~(0x1<<(sector-16));
|
||||
}
|
||||
else if (sector<32) {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)+2]&=~(0x1<<(sector-24));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"Error vtoc_reserve_sector! sector too big %d\n",sector);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dos33_vtoc_dump_bitmap(unsigned char *vtoc, int num_tracks) {
|
||||
|
||||
int i,j;
|
||||
|
||||
printf("\nFree sector bitmap:\n");
|
||||
printf("\tU=used, .=free\n");
|
||||
printf("\tTrack FEDCBA98 76543210\n");
|
||||
for(i=0;i<num_tracks;i++) {
|
||||
printf("\t $%02X: ",i);
|
||||
for(j=0;j<8;j++) {
|
||||
if ((vtoc[VTOC_FREE_BITMAPS+(i*4)]<<j)&0x80) {
|
||||
printf(".");
|
||||
}
|
||||
else {
|
||||
printf("U");
|
||||
}
|
||||
}
|
||||
printf(" ");
|
||||
for(j=0;j<8;j++) {
|
||||
if ((vtoc[VTOC_FREE_BITMAPS+(i*4)+1]<<j)&0x80) {
|
||||
printf(".");
|
||||
}
|
||||
else {
|
||||
printf("U");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* reserve a sector in the sector bitmap */
|
||||
int dos33_vtoc_find_free_sector(unsigned char *vtoc,
|
||||
int *found_track, int *found_sector) {
|
||||
|
||||
int start_track,track_dir,i;
|
||||
int bitmap;
|
||||
int found=0;
|
||||
|
||||
/* Originally used to keep things near center of disk for speed */
|
||||
/* We can use to avoid fragmentation possibly */
|
||||
start_track=vtoc[VTOC_LAST_ALLOC_T]%TRACKS_PER_DISK;
|
||||
track_dir=vtoc[VTOC_ALLOC_DIRECT];
|
||||
|
||||
if (track_dir==255) track_dir=-1;
|
||||
|
||||
if ((track_dir!=1) && (track_dir!=-1)) {
|
||||
fprintf(stderr,"ERROR! Invalid track dir %i\n",track_dir);
|
||||
}
|
||||
|
||||
if (((start_track>VOLDIR_TRACK) && (track_dir!=1)) ||
|
||||
((start_track<VOLDIR_TRACK) && (track_dir!=-1))) {
|
||||
fprintf(stderr,"Warning! Non-optimal values for track dir t=%i d=%i\n",
|
||||
start_track,track_dir);
|
||||
}
|
||||
|
||||
i=start_track;
|
||||
do {
|
||||
|
||||
/* i+1 = sector 0..7 */
|
||||
bitmap=vtoc[VTOC_FREE_BITMAPS+(i*4)+1];
|
||||
if (bitmap!=0x00) {
|
||||
*found_sector=find_first_one(bitmap);
|
||||
*found_track=i;
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* i+0 = sector 8..15 */
|
||||
bitmap=vtoc[VTOC_FREE_BITMAPS+(i*4)];
|
||||
if (bitmap!=0x00) {
|
||||
*found_sector=find_first_one(bitmap)+8;
|
||||
*found_track=i;
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next track, handling overflows */
|
||||
i+=track_dir;
|
||||
if (i<0) {
|
||||
i=VOLDIR_TRACK;
|
||||
track_dir=1;
|
||||
}
|
||||
if (i>=TRACKS_PER_DISK) {
|
||||
i=VOLDIR_TRACK;
|
||||
track_dir=-1;
|
||||
}
|
||||
} while (i!=start_track);
|
||||
|
||||
if (found) {
|
||||
/* clear bit indicating in use */
|
||||
dos33_vtoc_reserve_sector(vtoc, *found_track, *found_sector);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no room */
|
||||
return -1;
|
||||
|
||||
}
|
1
utils/prodos-utils/version.h
Normal file
1
utils/prodos-utils/version.h
Normal file
@ -0,0 +1 @@
|
||||
#define VERSION "0.0.12"
|
Loading…
Reference in New Issue
Block a user