mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-10-24 23:25:28 +00:00
Oldest version I can find.
This commit is contained in:
parent
1ee8be3a70
commit
b86c16fa1a
41
Makefile
Normal file
41
Makefile
Normal file
@ -0,0 +1,41 @@
|
||||
CC = gcc
|
||||
C_FLAGS = -O2 -Wall
|
||||
L_FLAGS =
|
||||
|
||||
all: dos33 asoft_detoken mkdos33fs make_b
|
||||
|
||||
|
||||
|
||||
asoft_detoken: asoft_detoken.o
|
||||
$(CC) $(L_FLAGS) -o asoft_detoken asoft_detoken.o
|
||||
|
||||
asoft_detoken.o: asoft_detoken.c
|
||||
$(CC) $(C_FLAGS) -c asoft_detoken.c
|
||||
|
||||
|
||||
|
||||
dos33: dos33.o
|
||||
$(CC) $(L_FLAGS) -o dos33 dos33.o
|
||||
|
||||
dos33.o: dos33.c dos33.h
|
||||
$(CC) $(C_FLAGS) -c dos33.c
|
||||
|
||||
make_b: make_b.o
|
||||
$(CC) $(L_FLAGS) -o make_b make_b.o
|
||||
|
||||
make_b.o: make_b.c
|
||||
$(CC) $(C_FLAGS) -c make_b.c
|
||||
|
||||
|
||||
mkdos33fs: mkdos33fs.o
|
||||
$(CC) $(L_FLAGS) -o mkdos33fs mkdos33fs.o
|
||||
|
||||
mkdos33fs.o: mkdos33fs.c dos33.h
|
||||
$(CC) $(C_FLAGS) -c mkdos33fs.c
|
||||
|
||||
|
||||
install:
|
||||
cp dos33 asoft_detoken mkdos33fs make_b /usr/local/bin
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o asoft_detoken dos33 make_b mkdos33fs
|
6
TODO
Normal file
6
TODO
Normal file
@ -0,0 +1,6 @@
|
||||
check lock before delete
|
||||
|
||||
defrag utility
|
||||
test-suite
|
||||
|
||||
test mkdosfs copy over DOS functionality
|
180
asoft_detoken.c
Normal file
180
asoft_detoken.c
Normal file
@ -0,0 +1,180 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* strlen() */
|
||||
|
||||
/* Starting at 0x80 */
|
||||
char applesoft_tokens[][8]={
|
||||
|
||||
/* 80 */ "END","FOR","NEXT","DATA","INPUT","DEL","DIM","READ",
|
||||
/* 88 */ "GR","TEXT","PR #","IN #","CALL","PLOT","HLIN","VLIN",
|
||||
/* 90 */ "HGR2","HGR","HCOLOR=","HPLOT","DRAW","XDRAW","HTAB","HOME",
|
||||
/* 98 */ "ROT=","SCALE=","SHLOAD","TRACE","NOTRACE","NORMAL","INVERSE","FLASH",
|
||||
/* A0 */ "COLOR=","POP","VTAB ","HIMEM:","LOMEM:","ONERR","RESUME","RECALL",
|
||||
/* A8 */ "STORE","SPEED=","LET","GOTO","RUN","IF","RESTORE","&",
|
||||
/* B0 */ "GOSUB","RETURN","REM","STOP","ON","WAIT","LOAD","SAVE",
|
||||
/* B8 */ "DEF FN","POKE","PRINT","CONT","LIST","CLEAR","GET","NEW",
|
||||
/* C0 */ "TAB","TO","FN","SPC(","THEN","AT","NOT","STEP",
|
||||
/* C8 */ "+","-","*","/","^","AND","OR",">",
|
||||
/* D0 */ "=","<","SGN","INT","ABS","USR","FRE","SCRN (",
|
||||
/* D8 */ "PDL","POS","SQR","RND","LOG","EXP","COS","SIN",
|
||||
/* E0 */ "TAN","ATN","PEEK","LEN","STR$","VAL","ASC","CHR$",
|
||||
/* E8 */ "LEFT$","RIGHT$","MID$","","","","","",
|
||||
/* F0 */ "","","","","","","","",
|
||||
/* F8 */ "","","","","","(","(","("
|
||||
};
|
||||
|
||||
/*
|
||||
Integer Basic
|
||||
|
||||
$03: :
|
||||
$04: LOAD
|
||||
$05: SAVE
|
||||
$07: RUN
|
||||
$09: DEL
|
||||
$0A: ,
|
||||
$0B: NEW
|
||||
$0C: CLR
|
||||
$0D: AUTO
|
||||
$0F: MAN
|
||||
$10: HIMEM:
|
||||
$11: LOMEM:
|
||||
$12: +
|
||||
$13: -
|
||||
$14: *
|
||||
$15: /
|
||||
$16: =
|
||||
$17: #
|
||||
$18: >=
|
||||
$19: >
|
||||
$1A: <=
|
||||
$1B: <>
|
||||
$1C: <
|
||||
$1D: AND
|
||||
$1E: OR
|
||||
$1F: MOD
|
||||
$20: ^
|
||||
$22: (
|
||||
$23: ,
|
||||
$24,
|
||||
$25: THEN
|
||||
$26,
|
||||
$27: ,
|
||||
$28, $29: \"
|
||||
$2A: (
|
||||
$2D: (
|
||||
$2E: PEEK
|
||||
$2F: RND
|
||||
$30: SGN
|
||||
$31: ABS
|
||||
$32: PDL
|
||||
$34: (
|
||||
$35: +
|
||||
$36: -
|
||||
$37: NOT
|
||||
$38: (
|
||||
$39: =
|
||||
$3A: #
|
||||
$3B: LEN (
|
||||
$3C: ASC (
|
||||
$3D: SCRN (
|
||||
$3E: ,
|
||||
$3F: (
|
||||
$40: $
|
||||
$42: (
|
||||
$43,
|
||||
$44: ,
|
||||
$45,
|
||||
$46,
|
||||
$47: ;
|
||||
$48,
|
||||
$49: ,
|
||||
$4A: ,
|
||||
$4B: TEXT
|
||||
$4C: GR
|
||||
$4D: CALL
|
||||
$4E,
|
||||
$4F: DIM
|
||||
$50: TAB
|
||||
$51: END
|
||||
$52, $53, $54: INPUT
|
||||
$55: FOR
|
||||
$56: =
|
||||
$57: TO
|
||||
$58: STEP
|
||||
$59: NEXT
|
||||
$5A: ,
|
||||
$5B: RETURN
|
||||
$5C: GOSUB
|
||||
$5D: REM
|
||||
$5E: LET
|
||||
$5F: GOTO
|
||||
$60: IF
|
||||
$61,
|
||||
$62: PRINT
|
||||
$63: PRINT
|
||||
$64: POKE
|
||||
$65: ,
|
||||
$66: COLOR=
|
||||
$67: PLOT
|
||||
$68: ,
|
||||
$69: HLIN
|
||||
$6A: ,
|
||||
$6B: AT
|
||||
$6C: VLIN
|
||||
$6D: ,
|
||||
$6E: AT
|
||||
$6F: VTAB
|
||||
$70,
|
||||
$71: =
|
||||
$72: )
|
||||
$74: LIST
|
||||
$75: ,
|
||||
$77: POP
|
||||
$79: NO DSP
|
||||
$7A: NO TRACE
|
||||
$7B,
|
||||
$7C: DSP
|
||||
$7D: TRACE
|
||||
$7E: PR #
|
||||
$7F: IN #
|
||||
|
||||
*/
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
int ch1,i;
|
||||
unsigned char size1,size2;
|
||||
unsigned char line1,line2;
|
||||
unsigned char eight,line_length;
|
||||
|
||||
|
||||
/* read size, first two bytes */
|
||||
size1=fgetc(stdin);
|
||||
size2=fgetc(stdin);
|
||||
|
||||
while(!feof(stdin)) {
|
||||
|
||||
|
||||
line_length=fgetc(stdin);
|
||||
eight=fgetc(stdin); /* sometimes 8, sometimes 9? */
|
||||
if (eight==0) goto the_end;
|
||||
line1=fgetc(stdin);
|
||||
line2=fgetc(stdin);
|
||||
if (feof(stdin)) goto the_end;
|
||||
printf("%4d ",(((int)line2)<<8)+line1);
|
||||
|
||||
while( (ch1=fgetc(stdin))!=0 ) {
|
||||
if (ch1>=0x80) {
|
||||
fputc(' ',stdout);
|
||||
for(i=0;i<strlen(applesoft_tokens[ch1-0x80]);i++) {
|
||||
fputc(applesoft_tokens[ch1-0x80][i],stdout);
|
||||
}
|
||||
fputc(' ',stdout);
|
||||
}
|
||||
else fputc(ch1,stdout);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
the_end:;
|
||||
return 0;
|
||||
}
|
978
dos33.c
Normal file
978
dos33.c
Normal file
@ -0,0 +1,978 @@
|
||||
#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() */
|
||||
|
||||
#define VERSION "0.4"
|
||||
|
||||
#include "dos33.h"
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
unsigned char dos33_file_type(int value) {
|
||||
|
||||
unsigned char result;
|
||||
|
||||
switch(value){
|
||||
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(unsigned char *dest,unsigned char *src) {
|
||||
|
||||
int i=0,last_nonspace=0;
|
||||
|
||||
for(i=0;i<30;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;
|
||||
|
||||
}
|
||||
|
||||
int dos33_read_vtoc(int fd,unsigned char *buffer) {
|
||||
/* Seek to VTOC */
|
||||
lseek(fd,DISK_OFFSET(VTOC_TRACK,VTOC_SECTOR),SEEK_SET);
|
||||
/* read in VTOC */
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dos33_free_space(int fd, unsigned char *buffer) {
|
||||
|
||||
unsigned char bitmap[4];
|
||||
int i,sectors_free=0;
|
||||
|
||||
/* Read Vtoc */
|
||||
dos33_read_vtoc(fd,buffer);
|
||||
|
||||
for(i=0;i<TRACKS_PER_DISK;i++) {
|
||||
bitmap[0]=buffer[VTOC_FREE_BITMAPS+(i*4)];
|
||||
bitmap[1]=buffer[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];
|
||||
|
||||
// printf("%i: 0x%x 0x%x\n",i,bitmap[0],bitmap[1]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return sectors_free*BYTES_PER_SECTOR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int dos33_get_catalog_ts(int fd,unsigned char *buffer) {
|
||||
dos33_read_vtoc(fd,buffer);
|
||||
|
||||
return TS_TO_INT(buffer[VTOC_CATALOG_T],buffer[VTOC_CATALOG_S]);
|
||||
}
|
||||
|
||||
int dos33_find_next_file(int fd,int catalog_tsf,unsigned char *buffer) {
|
||||
|
||||
|
||||
int catalog_track,catalog_sector,catalog_file;
|
||||
int file_track,i;
|
||||
|
||||
catalog_file=catalog_tsf>>16;
|
||||
catalog_track=(catalog_tsf>>8)&0xff;
|
||||
catalog_sector=(catalog_tsf&0xff);
|
||||
|
||||
catalog_loop:
|
||||
|
||||
/* Read in Catalog Sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
i=catalog_file;
|
||||
while(i<7) {
|
||||
|
||||
file_track=buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)];
|
||||
/* 0xff means file deleted */
|
||||
/* 0x0 means empty */
|
||||
if ((file_track!=0xff) && (file_track!=0x0)){
|
||||
return ((i<<16)+(catalog_track<<8)+catalog_sector);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
catalog_track=buffer[CATALOG_NEXT_T];
|
||||
catalog_sector=buffer[CATALOG_NEXT_S];
|
||||
if (catalog_sector!=0) goto catalog_loop;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dos33_print_file_info(int fd,int catalog_tsf,unsigned char *buffer) {
|
||||
|
||||
int catalog_track,catalog_sector,catalog_file;
|
||||
char temp_string[BUFSIZ];
|
||||
|
||||
catalog_file=catalog_tsf>>16;
|
||||
catalog_track=(catalog_tsf>>8)&0xff;
|
||||
catalog_sector=(catalog_tsf&0xff);
|
||||
|
||||
|
||||
/* Read in Catalog Sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
if (buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]>0x7f) {
|
||||
printf("*");
|
||||
}
|
||||
else printf(" ");
|
||||
|
||||
printf("%c",dos33_file_type(buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]));
|
||||
printf(" ");
|
||||
printf("%.3i ",buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_SIZE_L)]+
|
||||
(buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_SIZE_H)]<<8));
|
||||
|
||||
|
||||
printf("%s",dos33_filename_to_ascii(temp_string,
|
||||
buffer+(CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE+FILE_NAME))));
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int dos33_check_file_exists(int fd,char *filename,unsigned char *buffer) {
|
||||
|
||||
int catalog_track=0,catalog_sector=0;
|
||||
int i,file_track;
|
||||
char file_name[31];
|
||||
|
||||
dos33_read_vtoc(fd,buffer);
|
||||
|
||||
catalog_track=buffer[VTOC_CATALOG_T];
|
||||
catalog_sector=buffer[VTOC_CATALOG_S];
|
||||
|
||||
repeat_catalog:
|
||||
|
||||
/* Read in Catalog Sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
for(i=0;i<7;i++) {
|
||||
file_track=buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)];
|
||||
/* 0xff means file deleted */
|
||||
/* 0x0 means empty */
|
||||
if ((file_track!=0xff) && (file_track!=0x0)){
|
||||
|
||||
dos33_filename_to_ascii(file_name,
|
||||
buffer+(CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE+FILE_NAME)));
|
||||
|
||||
if (!strncmp(filename,file_name,30)) return ((i<<16)+(catalog_track<<8)+catalog_sector);
|
||||
}
|
||||
|
||||
}
|
||||
catalog_track=buffer[CATALOG_NEXT_T];
|
||||
catalog_sector=buffer[CATALOG_NEXT_S];
|
||||
|
||||
if (catalog_sector!=0) goto repeat_catalog;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int find_first_one(unsigned char byte) {
|
||||
|
||||
int i=0;
|
||||
|
||||
while((byte& (0x1<<i))==0) {
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int dos33_free_sector(int fd,int track,int sector) {
|
||||
|
||||
|
||||
unsigned char vtoc[BYTES_PER_SECTOR];
|
||||
|
||||
/* Seek to VTOC */
|
||||
lseek(fd,DISK_OFFSET(VTOC_TRACK,VTOC_SECTOR),SEEK_SET);
|
||||
/* read in VTOC */
|
||||
read(fd,&vtoc,BYTES_PER_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 {
|
||||
vtoc[VTOC_FREE_BITMAPS+(track*4)]|=(0x1<<(sector-8));
|
||||
}
|
||||
|
||||
/* write modified VTOC back out */
|
||||
lseek(fd,DISK_OFFSET(VTOC_TRACK,VTOC_SECTOR),SEEK_SET);
|
||||
write(fd,&vtoc,BYTES_PER_SECTOR);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int dos33_allocate_sector(int fd) {
|
||||
|
||||
int found_track=0,found_sector=0;
|
||||
unsigned char bitmap[4],buffer[BYTES_PER_SECTOR];
|
||||
int i,start_track,track_dir,byte;
|
||||
|
||||
dos33_read_vtoc(fd,buffer);
|
||||
|
||||
/* Originally used to keep things near center of disk for speed */
|
||||
/* We can use to avoid fragmentation possibly */
|
||||
start_track=buffer[VTOC_LAST_ALLOC_T]%TRACKS_PER_DISK;
|
||||
track_dir=buffer[VTOC_ALLOC_DIRECT];
|
||||
|
||||
if ((track_dir!=1) && (track_dir!=-1))
|
||||
printf("ERROR! Invalid track dir %i\n",track_dir);
|
||||
|
||||
if (((start_track>VTOC_TRACK) && (track_dir!=1)) ||
|
||||
((start_track<VTOC_TRACK) && (track_dir!=-1)))
|
||||
printf("Warning! Non-optimal values for track dir t=%i d=%i!\n",
|
||||
start_track,track_dir);
|
||||
|
||||
|
||||
i=start_track;
|
||||
|
||||
do {
|
||||
|
||||
for(byte=0;byte<2;byte++) {
|
||||
|
||||
bitmap[byte]=buffer[VTOC_FREE_BITMAPS+(i*4)+byte];
|
||||
if (bitmap[byte]!=0x00) {
|
||||
found_sector=find_first_one(bitmap[byte]);
|
||||
found_track=i;
|
||||
/* clear bit indicating in use */
|
||||
buffer[VTOC_FREE_BITMAPS+(i*4)+byte]&=~(0x1<<found_sector);
|
||||
found_sector+=(8*byte);
|
||||
goto found_one;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to next track, handling overflows */
|
||||
i+=track_dir;
|
||||
if (i<0) {
|
||||
i=VTOC_TRACK;
|
||||
track_dir=1;
|
||||
}
|
||||
|
||||
if (i>=TRACKS_PER_DISK) {
|
||||
i=VTOC_TRACK;
|
||||
track_dir=-1;
|
||||
}
|
||||
|
||||
} while (i!=start_track);
|
||||
|
||||
printf("No room left!\n");
|
||||
return -1;
|
||||
|
||||
found_one:
|
||||
/* store new track/direction info */
|
||||
buffer[VTOC_LAST_ALLOC_T]=found_track;
|
||||
|
||||
if (found_track>VTOC_TRACK) buffer[VTOC_ALLOC_DIRECT]=1;
|
||||
else buffer[VTOC_ALLOC_DIRECT]=-1;
|
||||
|
||||
/* Seek to VTOC */
|
||||
lseek(fd,DISK_OFFSET(VTOC_TRACK,VTOC_SECTOR),SEEK_SET);
|
||||
/* Write out VTOC */
|
||||
write(fd,&buffer,BYTES_PER_SECTOR);
|
||||
return ((found_track<<8)+found_sector);
|
||||
}
|
||||
|
||||
int dos33_add_file(int fd,char type,char *filename,char *apple_filename,
|
||||
unsigned char *buffer) {
|
||||
|
||||
int free_space,file_size;
|
||||
struct stat file_info;
|
||||
int size_in_sectors=0;
|
||||
int initial_ts_list=0,ts_list=0,i,data_ts,x,bytes_read=0,old_ts_list;
|
||||
int catalog_track,catalog_sector,sectors_used=0;
|
||||
int input_fd;
|
||||
|
||||
/* FIXME */
|
||||
/* check type */
|
||||
/* and sanity check a/b filesize is set properly */
|
||||
|
||||
|
||||
|
||||
/* Determine size of file to upload */
|
||||
if (stat(filename,&file_info)<0) {
|
||||
printf("Error! %s not found!\n",filename);
|
||||
exit(3);
|
||||
}
|
||||
file_size=(int)file_info.st_size;
|
||||
|
||||
/* Get free space on device */
|
||||
free_space=dos33_free_space(fd,buffer);
|
||||
|
||||
/* Check for free space */
|
||||
/* Really, this is not enough. */
|
||||
/* We need an extra sector for a T/S list every 122*256 bytes (~31k) */
|
||||
if (file_size>free_space) {
|
||||
printf("Error! Not enough free space on disk image\n");
|
||||
}
|
||||
|
||||
/* plus one because we need a sector for the tail */
|
||||
size_in_sectors=(file_size/BYTES_PER_SECTOR)+1;
|
||||
printf("Need to allocate %i data sectors\n",size_in_sectors);
|
||||
|
||||
/* Open the local file */
|
||||
input_fd=open(filename,O_RDONLY);
|
||||
if (input_fd<0) {
|
||||
printf("Error! could not open %s\n",filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
i=0;
|
||||
while (i<size_in_sectors) {
|
||||
|
||||
/* Create new T/S list if necessary */
|
||||
if (i%TSL_MAX_NUMBER==0) {
|
||||
old_ts_list=ts_list;
|
||||
|
||||
/* allocate a sector for the new list */
|
||||
ts_list=dos33_allocate_sector(fd);
|
||||
sectors_used++;
|
||||
if (ts_list<0) return -1;
|
||||
|
||||
/* clear the t/s sector */
|
||||
for(x=0;x<BYTES_PER_SECTOR;x++) buffer[x]=0;
|
||||
lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
|
||||
write(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
if (i==0) initial_ts_list=ts_list;
|
||||
else {
|
||||
/* we aren't the first t/s list so do special stuff */
|
||||
|
||||
/* load in the old t/s list */
|
||||
lseek(fd,DISK_OFFSET((old_ts_list>>8)&0xff,old_ts_list&0xff),SEEK_SET);
|
||||
read(fd,&buffer,BYTES_PER_SECTOR);
|
||||
|
||||
/* point from old ts list to new one we just made */
|
||||
buffer[TSL_NEXT_TRACK]=(ts_list>>8)&0xff;
|
||||
buffer[TSL_NEXT_SECTOR]=(ts_list)&0xff;
|
||||
|
||||
/* set offset into file */
|
||||
buffer[TSL_OFFSET_H]=(((i-122)*256)>>8)&0xff;
|
||||
buffer[TSL_OFFSET_L]=(((i-122)*256)&0xff);
|
||||
|
||||
/* write out the old t/s list with updated info */
|
||||
lseek(fd,DISK_OFFSET((old_ts_list>>8)&0xff,old_ts_list&0xff),SEEK_SET);
|
||||
write(fd,buffer,BYTES_PER_SECTOR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* allocate a sector */
|
||||
data_ts=dos33_allocate_sector(fd);
|
||||
sectors_used++;
|
||||
|
||||
if (data_ts<0) return -1;
|
||||
|
||||
/* clear sector */
|
||||
for(x=0;x<BYTES_PER_SECTOR;x++) buffer[x]=0;
|
||||
|
||||
/* read from input */
|
||||
bytes_read=read(input_fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
/* write to disk image */
|
||||
lseek(fd,DISK_OFFSET((data_ts>>8)&0xff,data_ts&0xff),SEEK_SET);
|
||||
write(fd,buffer,BYTES_PER_SECTOR);
|
||||
// printf("Writing %i bytes to %i/%i\n",bytes_read,(data_ts>>8)&0xff,
|
||||
// data_ts&0xff);
|
||||
|
||||
|
||||
|
||||
/* add to T/s table */
|
||||
|
||||
/* read in t/s list */
|
||||
lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
/* point to new data sector */
|
||||
buffer[((i%TSL_MAX_NUMBER)*2)+TSL_LIST]=(data_ts>>8)&0xff;
|
||||
buffer[((i%TSL_MAX_NUMBER)*2)+TSL_LIST+1]=(data_ts&0xff);
|
||||
|
||||
/* write t/s list back out */
|
||||
lseek(fd,DISK_OFFSET((ts_list>>8)&0xff,ts_list&0xff),SEEK_SET);
|
||||
write(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Add new file to Catalog */
|
||||
|
||||
/* read in vtoc */
|
||||
dos33_read_vtoc(fd,buffer);
|
||||
|
||||
catalog_track=buffer[VTOC_CATALOG_T];
|
||||
catalog_sector=buffer[VTOC_CATALOG_S];
|
||||
|
||||
continue_parsing_catalog:
|
||||
|
||||
/* Read in Catalog Sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
/* Find empty directory entry */
|
||||
i=0;
|
||||
while(i<7) {
|
||||
if ((buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]==0xff) ||
|
||||
(buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]==0x00))
|
||||
goto got_a_dentry;
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((catalog_track=0x11) && (catalog_sector==1)) {
|
||||
/* in theory can only have 105 files */
|
||||
/* if full, we have no recourse! */
|
||||
/* can we allocate new catalog sectors and point to them?? */
|
||||
printf("Error! No more room for files!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
catalog_track=buffer[CATALOG_NEXT_T];
|
||||
catalog_sector=buffer[CATALOG_NEXT_S];
|
||||
|
||||
goto continue_parsing_catalog;
|
||||
|
||||
got_a_dentry:
|
||||
// printf("Adding file at entry %i of catalog 0x%x:0x%x\n",
|
||||
// i,catalog_track,catalog_sector);
|
||||
|
||||
/* Point entry to initial t/s list */
|
||||
buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)]=(initial_ts_list>>8)&0xff;
|
||||
buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+1]=(initial_ts_list&0xff);
|
||||
/* set file type */
|
||||
buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_TYPE]=
|
||||
dos33_char_to_type(type,0);
|
||||
|
||||
// printf("Pointing T/S to %x/%x\n",(initial_ts_list>>8)&0xff,initial_ts_list&0xff);
|
||||
|
||||
/* copy over filename */
|
||||
for(x=0;x<strlen(apple_filename);x++)
|
||||
buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_NAME+x]=
|
||||
apple_filename[x]^0x80;
|
||||
|
||||
/* pad out the filename with spaces */
|
||||
for(x=strlen(apple_filename);x<FILE_NAME_SIZE;x++)
|
||||
buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_NAME+x]=' '^0x80;
|
||||
|
||||
/* fill in filesize in sectors */
|
||||
buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_SIZE_L]=
|
||||
sectors_used&0xff;
|
||||
buffer[CATALOG_FILE_LIST+(i*CATALOG_ENTRY_SIZE)+FILE_SIZE_H]=
|
||||
(sectors_used>>8)&0xff;
|
||||
|
||||
/* write out catalog sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
write(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dos33_load_file(int fd,int fts,char *filename,unsigned char *buffer) {
|
||||
|
||||
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[BYTES_PER_SECTOR];
|
||||
int tsl_pointer=0,output_pointer=0;
|
||||
|
||||
output_fd=open(filename,O_WRONLY|O_CREAT,0666);
|
||||
if (output_fd<0) {
|
||||
printf("Error! could not open %s for local save\n",filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
catalog_file=fts>>16;
|
||||
catalog_track=(fts>>8)&0xff;
|
||||
catalog_sector=(fts&0xff);
|
||||
|
||||
|
||||
/* Read in Catalog Sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
tsl_track=buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TS_LIST_T];
|
||||
tsl_sector=buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TS_LIST_S];
|
||||
file_type=dos33_file_type(buffer[CATALOG_FILE_LIST+(catalog_file*CATALOG_ENTRY_SIZE)+FILE_TYPE]);
|
||||
|
||||
printf("file_type: %c\n",file_type);
|
||||
|
||||
keep_savin:
|
||||
/* Read in TSL Sector */
|
||||
lseek(fd,DISK_OFFSET(tsl_track,tsl_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
|
||||
while(tsl_pointer<TSL_MAX_NUMBER) {
|
||||
|
||||
data_t=buffer[TSL_LIST+(tsl_pointer*TSL_ENTRY_SIZE)];
|
||||
data_s=buffer[TSL_LIST+(tsl_pointer*TSL_ENTRY_SIZE)+1];
|
||||
|
||||
|
||||
if ((data_s==0) && (data_t==0)) {
|
||||
}
|
||||
else {
|
||||
lseek(fd,DISK_OFFSET(data_t,data_s),SEEK_SET);
|
||||
read(fd,&data_sector,BYTES_PER_SECTOR);
|
||||
|
||||
/* Cheat and get real file size from file itself */
|
||||
if (tsl_pointer==0) {
|
||||
switch(file_type) {
|
||||
case 'A':
|
||||
case 'I':
|
||||
file_size=data_sector[0]+(data_sector[1]<<8)+2;
|
||||
break;
|
||||
case 'B':
|
||||
file_size=data_sector[2]+(data_sector[3]<<8)+4;
|
||||
break;
|
||||
default:
|
||||
file_size=-1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
lseek(output_fd,output_pointer*BYTES_PER_SECTOR,SEEK_SET);
|
||||
write(output_fd,&data_sector,BYTES_PER_SECTOR);
|
||||
}
|
||||
output_pointer++;
|
||||
tsl_pointer++;
|
||||
}
|
||||
tsl_track=buffer[TSL_NEXT_TRACK];
|
||||
tsl_sector=buffer[TSL_NEXT_SECTOR];
|
||||
|
||||
if ((tsl_track==0) && (tsl_sector==0)) {
|
||||
}
|
||||
else goto keep_savin;
|
||||
|
||||
/* Correct the file size */
|
||||
if (file_size>=0) {
|
||||
ftruncate(output_fd,file_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int dos33_delete_file(int fd,int fsl,unsigned char *buffer) {
|
||||
|
||||
int i;
|
||||
int catalog_track,catalog_sector,catalog_entry;
|
||||
int ts_track,ts_sector;
|
||||
|
||||
/* unpack file/track/sector info */
|
||||
catalog_entry=fsl>>16;
|
||||
catalog_track=(fsl>>8)&0xff;
|
||||
catalog_sector=(fsl&0xff);
|
||||
|
||||
/* Load in the catalog table for the file */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
/* get pointer to t/s list */
|
||||
ts_track=buffer[CATALOG_FILE_LIST+catalog_entry*CATALOG_ENTRY_SIZE+
|
||||
FILE_TS_LIST_T];
|
||||
ts_sector=buffer[CATALOG_FILE_LIST+catalog_entry*CATALOG_ENTRY_SIZE+
|
||||
FILE_TS_LIST_S];
|
||||
|
||||
keep_deleting:
|
||||
|
||||
|
||||
|
||||
/* load in the t/s list info */
|
||||
lseek(fd,DISK_OFFSET(ts_track,ts_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
/* Free each sector listed by t/s list */
|
||||
for(i=0;i<TSL_MAX_NUMBER;i++) {
|
||||
/* If t/s = 0/0 then no need to clear */
|
||||
if ((buffer[TSL_LIST+2*i]==0) && (buffer[TSL_LIST+2*i+1]==0)) {
|
||||
}
|
||||
else {
|
||||
dos33_free_sector(fd,buffer[TSL_LIST+2*i],buffer[TSL_LIST+2*i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* free the t/s list */
|
||||
dos33_free_sector(fd,ts_track,ts_sector);
|
||||
|
||||
/* Point to next t/s list */
|
||||
ts_track=buffer[TSL_NEXT_TRACK];
|
||||
ts_sector=buffer[TSL_NEXT_SECTOR];
|
||||
|
||||
/* If more tsl lists, keep looping */
|
||||
if ((ts_track==0x0) && (ts_sector==0x0)) {
|
||||
}
|
||||
else {
|
||||
goto keep_deleting;
|
||||
}
|
||||
|
||||
/* Erase file from catalog entry */
|
||||
|
||||
/* First reload proper catalog sector */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
read(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
/* save track as last char of name, for undelete purposes */
|
||||
buffer[CATALOG_FILE_LIST+(catalog_entry*CATALOG_ENTRY_SIZE)+
|
||||
(FILE_NAME+FILE_NAME_SIZE-1)]=
|
||||
buffer[CATALOG_FILE_LIST+(catalog_entry*CATALOG_ENTRY_SIZE)];
|
||||
|
||||
/* Actually delete the file */
|
||||
/* by setting the track value to FF which indicates deleted file */
|
||||
buffer[CATALOG_FILE_LIST+(catalog_entry*CATALOG_ENTRY_SIZE)]=0xff;
|
||||
|
||||
/* re seek to catalog position and write out changes */
|
||||
lseek(fd,DISK_OFFSET(catalog_track,catalog_sector),SEEK_SET);
|
||||
write(fd,buffer,BYTES_PER_SECTOR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int display_help(char *name) {
|
||||
printf("\n%s version %s\n",name,VERSION);
|
||||
printf("by Vince Weaver <vince@deater.net>\n");
|
||||
printf("\n");
|
||||
printf("Usage: %s disk_image COMMAND\n",name);
|
||||
printf(" Where disk_image is a valid dos3.3 disk image\n"
|
||||
" and COMMAND is one of the following:\n");
|
||||
printf("\tCATALOG\n");
|
||||
printf("\tLOAD apple_file <local_file>\n");
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define COMMAND_UNKNOWN 0
|
||||
#define COMMAND_LOAD 1
|
||||
#define COMMAND_SAVE 2
|
||||
#define COMMAND_BLOAD 3
|
||||
#define COMMAND_BSAVE 4
|
||||
#define COMMAND_CATALOG 5
|
||||
#define COMMAND_DELETE 6
|
||||
#define COMMAND_UNDELETE 7
|
||||
#define COMMAND_LOCK 8
|
||||
#define COMMAND_UNLOCK 9
|
||||
#define COMMAND_INIT 10
|
||||
#define COMMAND_UPLOAD 11
|
||||
#define COMMAND_DNLOAD 12
|
||||
#define COMMAND_VERIFY 13
|
||||
#define COMMAND_RENAME 14
|
||||
#define COMMAND_COPY 15
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char image[BUFSIZ];
|
||||
unsigned char type='b';
|
||||
int dos_fd=0,i;
|
||||
|
||||
int command,catalog;
|
||||
char temp_string[BUFSIZ];
|
||||
char apple_filename[31];
|
||||
char output_filename[BUFSIZ];
|
||||
|
||||
unsigned char scratch_sector[BYTES_PER_SECTOR];
|
||||
|
||||
if (argc<3) {
|
||||
printf("\nInvalid arguments!\n");
|
||||
display_help(argv[0]);
|
||||
goto exit_program;
|
||||
}
|
||||
|
||||
strncpy(temp_string,argv[2],BUFSIZ);
|
||||
for(i=0;i<strlen(temp_string);i++) temp_string[i]=toupper(temp_string[i]);
|
||||
|
||||
if (!strncmp(temp_string,"LOAD",4)) {
|
||||
command=COMMAND_LOAD;
|
||||
}
|
||||
else if (!strncmp(temp_string,"SAVE",4)) {
|
||||
command=COMMAND_SAVE;
|
||||
}
|
||||
else if (!strncmp(temp_string,"BLOAD",5)) {
|
||||
command=COMMAND_BLOAD;
|
||||
}
|
||||
else if (!strncmp(temp_string,"BSAVE",5)) {
|
||||
command=COMMAND_BSAVE;
|
||||
}
|
||||
else if (!strncmp(temp_string,"CATALOG",7)) {
|
||||
command=COMMAND_CATALOG;
|
||||
}
|
||||
else if (!strncmp(temp_string,"DELETE",6)) {
|
||||
command=COMMAND_DELETE;
|
||||
}
|
||||
else if (!strncmp(temp_string,"UNDELETE",8)) {
|
||||
command=COMMAND_UNDELETE;
|
||||
}
|
||||
else if (!strncmp(temp_string,"LOCK",4)) {
|
||||
command=COMMAND_LOCK;
|
||||
}
|
||||
else if (!strncmp(temp_string,"UNLOCK",6)) {
|
||||
command=COMMAND_UNLOCK;
|
||||
}
|
||||
else if (!strncmp(temp_string,"INIT",4)) {
|
||||
command=COMMAND_INIT;
|
||||
}
|
||||
else if (!strncmp(temp_string,"UPLOAD",6)) {
|
||||
command=COMMAND_UPLOAD;
|
||||
}
|
||||
else if (!strncmp(temp_string,"DNLOAD",6)) {
|
||||
command=COMMAND_DNLOAD;
|
||||
}
|
||||
else if (!strncmp(temp_string,"VERIFY",6)) {
|
||||
command=COMMAND_VERIFY;
|
||||
}
|
||||
else if (!strncmp(temp_string,"RENAME",6)) {
|
||||
command=COMMAND_RENAME;
|
||||
}
|
||||
else if (!strncmp(temp_string,"COPY",4)) {
|
||||
command=COMMAND_COPY;
|
||||
}
|
||||
else {
|
||||
display_help(argv[0]);
|
||||
goto exit_program;
|
||||
}
|
||||
|
||||
strncpy(image,argv[1],BUFSIZ);
|
||||
dos_fd=open(image,O_RDWR);
|
||||
if (dos_fd<0) {
|
||||
printf("Error opening disk_image: %s\n",image);
|
||||
exit(4);
|
||||
}
|
||||
|
||||
switch(command) {
|
||||
case COMMAND_LOAD:
|
||||
case COMMAND_BLOAD:
|
||||
if (argc<4) {
|
||||
printf("Error! Need apple file_name\n");
|
||||
printf("%s %s LOAD apple_filename\n",argv[0],image);
|
||||
goto exit_and_close;
|
||||
}
|
||||
if (strlen(argv[3])>30) {
|
||||
printf("Warning! Truncating %s to 30 chars\n",argv[3]);
|
||||
}
|
||||
strncpy(apple_filename,argv[3],30);
|
||||
apple_filename[31]='\0';
|
||||
|
||||
if (argc==5) {
|
||||
strncpy(output_filename,argv[4],BUFSIZ);
|
||||
}
|
||||
else {
|
||||
strncpy(output_filename,apple_filename,30);
|
||||
}
|
||||
|
||||
catalog=dos33_check_file_exists(dos_fd,apple_filename,scratch_sector);
|
||||
if (catalog<0) {
|
||||
printf("Error! %s not found!\n",apple_filename);
|
||||
goto exit_and_close;
|
||||
}
|
||||
|
||||
dos33_load_file(dos_fd,catalog,output_filename,scratch_sector);
|
||||
|
||||
|
||||
break;
|
||||
case COMMAND_CATALOG:
|
||||
|
||||
/* get first catalog */
|
||||
catalog=dos33_get_catalog_ts(dos_fd,scratch_sector);
|
||||
|
||||
printf("\nDISK VOLUME %i\n\n",scratch_sector[VTOC_DISK_VOLUME]);
|
||||
while(catalog>0) {
|
||||
catalog=dos33_find_next_file(dos_fd,catalog,scratch_sector);
|
||||
if (catalog>0) {
|
||||
dos33_print_file_info(dos_fd,catalog,scratch_sector);
|
||||
catalog+=(1<<16);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
|
||||
case COMMAND_SAVE:
|
||||
|
||||
/* argv3 == type == A,B,T,I, N,L etc */
|
||||
/* argv4 == name of local file */
|
||||
/* argv5 == optional name of file on disk image */
|
||||
|
||||
if (argc<5) {
|
||||
printf("Error! Need type and file_name\n");
|
||||
printf("%s %s SAVE type file_name apple_filename\n",argv[0],image);
|
||||
goto exit_and_close;
|
||||
}
|
||||
|
||||
type=argv[3][0];
|
||||
|
||||
if (argc==6) {
|
||||
if (strlen(argv[5])>30) {
|
||||
printf("Warning! Truncating filename to 30 chars!\n");
|
||||
}
|
||||
strncpy(apple_filename,argv[5],30);
|
||||
apple_filename[31]=0;
|
||||
}
|
||||
else {
|
||||
if (strlen(argv[4])>30) {
|
||||
printf("Warning! Truncating filename to 30 chars!\n");
|
||||
}
|
||||
strncpy(apple_filename,argv[4],30);
|
||||
apple_filename[31]=0;
|
||||
}
|
||||
|
||||
catalog=dos33_check_file_exists(dos_fd,apple_filename,scratch_sector);
|
||||
if (catalog>=0) {
|
||||
printf("Warning! %s exists!\n",apple_filename);
|
||||
printf("Over-write (y/n)?");
|
||||
fgets(temp_string,BUFSIZ,stdin);
|
||||
if (temp_string[0]!='y') {
|
||||
printf("Exiting early...\n");
|
||||
goto exit_and_close;
|
||||
}
|
||||
printf("Deleting previous version...\n");
|
||||
dos33_delete_file(dos_fd,catalog,scratch_sector);
|
||||
}
|
||||
|
||||
dos33_add_file(dos_fd,type,argv[4],apple_filename,scratch_sector);
|
||||
|
||||
|
||||
break;
|
||||
case COMMAND_BSAVE:
|
||||
|
||||
case COMMAND_DELETE:
|
||||
if (argc<4) {
|
||||
printf("Error! Need file_name\n");
|
||||
printf("%s %s DELETE apple_filename\n",argv[0],image);
|
||||
goto exit_and_close;
|
||||
}
|
||||
catalog=dos33_check_file_exists(dos_fd,argv[3],scratch_sector);
|
||||
if (catalog<0) {
|
||||
printf("Error! File %s does not exist\n",argv[3]);
|
||||
goto exit_and_close;
|
||||
}
|
||||
dos33_delete_file(dos_fd,catalog,scratch_sector);
|
||||
break;
|
||||
|
||||
case COMMAND_UNDELETE:
|
||||
case COMMAND_LOCK:
|
||||
case COMMAND_UNLOCK:
|
||||
case COMMAND_INIT:
|
||||
case COMMAND_UPLOAD:
|
||||
case COMMAND_DNLOAD:
|
||||
case COMMAND_VERIFY:
|
||||
case COMMAND_RENAME:
|
||||
case COMMAND_COPY:
|
||||
default:
|
||||
printf("Sorry, unsupported command\n");
|
||||
goto exit_and_close;
|
||||
}
|
||||
#if 0
|
||||
|
||||
|
||||
|
||||
type=argv[3][0];
|
||||
|
||||
if (type<'a') type+=0x20;
|
||||
if ((type!='a') && (type!='b') && (type!='t')) {
|
||||
printf("Error! Type must be A, B, or T!\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
printf("Adding \"%s\" to image \"%s\" type %c\n\n",
|
||||
filename,image,type);
|
||||
|
||||
|
||||
if (dos33_check_file_exists(dos_fd,filename)) {
|
||||
char temp_input[BUFSIZ];
|
||||
printf("Error! File %s already exists on %s!\n",filename,image);
|
||||
printf("Overwrite? (y/n)");
|
||||
scanf("%s",temp_input);
|
||||
if (temp_input[0]=='y') {
|
||||
dos33_delete_file(dos_fd,filename);
|
||||
printf("Deleting old file %s\n",filename);
|
||||
exit(5);
|
||||
}
|
||||
else {
|
||||
exit(5);
|
||||
}
|
||||
}
|
||||
|
||||
dos33_add_file(dos_fd,filename,file_size,type);
|
||||
#endif
|
||||
|
||||
|
||||
exit_and_close:
|
||||
close(dos_fd);
|
||||
exit_program:
|
||||
|
||||
return 0;
|
||||
}
|
54
dos33.h
Normal file
54
dos33.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* 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 SECTORS_PER_TRACK 0x10
|
||||
#define BYTES_PER_SECTOR 0x100
|
||||
|
||||
#define VTOC_TRACK 0x11
|
||||
#define VTOC_SECTOR 0x00
|
||||
|
||||
/* 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)*SECTORS_PER_TRACK)+(__sector))*BYTES_PER_SECTOR)
|
58
make_b.c
Normal file
58
make_b.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h> /* struct stat */
|
||||
#include <stdlib.h> /* exit() */
|
||||
#include <fcntl.h> /* open() */
|
||||
#include <unistd.h> /* close() */
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
int in_fd,out_fd,offset;
|
||||
|
||||
unsigned char buffer[256];
|
||||
int result,file_size;
|
||||
|
||||
struct stat file_info;
|
||||
|
||||
if (argc!=4) {
|
||||
printf("Usage: %s in_file out_file offset\n\n",argv[0]);
|
||||
printf("\tin_file : input file\n");
|
||||
printf("\tout_file : output file\n");
|
||||
printf("\toffset : offset which file should be loaded\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (stat(argv[1],&file_info)<0) {
|
||||
printf("Error! %s not found!\n",argv[1]);
|
||||
exit(2);
|
||||
}
|
||||
file_size=(int)file_info.st_size;
|
||||
|
||||
if ((in_fd=open(argv[1],O_RDONLY))<0) {
|
||||
printf("Error opening %s!\n",argv[1]);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
if ((out_fd=open(argv[2],O_WRONLY|O_CREAT,0666))<0) {
|
||||
printf("Error opening %s\n",argv[2]);
|
||||
exit(4);
|
||||
}
|
||||
|
||||
offset=strtol(argv[3],NULL,0);
|
||||
|
||||
buffer[0]=offset&0xff;
|
||||
buffer[1]=(offset>>8)&0xff;
|
||||
buffer[2]=file_size&0xff;
|
||||
buffer[3]=(file_size>>8)&0xff;
|
||||
|
||||
write(out_fd,&buffer,4);
|
||||
|
||||
while( (result=read(in_fd,&buffer,256))>0) {
|
||||
write(out_fd,&buffer,result);
|
||||
}
|
||||
|
||||
|
||||
close(in_fd);
|
||||
close(out_fd);
|
||||
|
||||
return 0;
|
||||
}
|
196
mkdos33fs.c
Normal file
196
mkdos33fs.c
Normal file
@ -0,0 +1,196 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* strncpy() */
|
||||
#include <fcntl.h> /* open() */
|
||||
#include <unistd.h> /* close() */
|
||||
#include <stdlib.h> /* strtol() */
|
||||
|
||||
#include "dos33.h"
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
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] device_name\n\n",binary);
|
||||
printf("\t-t tracks : number of tracks in filesystem\n");
|
||||
printf("\t-s sectors : number of sectors in filesystem\n");
|
||||
printf("\t-b blocksize : size of sector, in bytes\n");
|
||||
printf("\t-d filename : file to copy first 3 tracks over from\n");
|
||||
printf("\n\n");
|
||||
}
|
||||
exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
int num_tracks=35,num_sectors=16,block_size=256;
|
||||
int fd,dos_fd;
|
||||
char device[BUFSIZ],dos_src[BUFSIZ];
|
||||
char *buffer,*endptr;
|
||||
int i,c,copy_dos=0;
|
||||
|
||||
|
||||
|
||||
/* Parse Command Line Arguments */
|
||||
|
||||
while ((c = getopt (argc, argv,"t:s:b:d: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': block_size=strtol(optarg,&endptr,10);
|
||||
if ( endptr == optarg ) usage(argv[0], 1);
|
||||
break;
|
||||
|
||||
case 'd': copy_dos=1;
|
||||
strncpy(dos_src,optarg,BUFSIZ);
|
||||
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);
|
||||
|
||||
/* Sanity check values */
|
||||
|
||||
/* s 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;
|
||||
}
|
||||
|
||||
/* t 17->(block_size-0x38)/2 */
|
||||
if ((num_tracks<18) || (num_tracks>(block_size-0x38)/2)) {
|
||||
printf("Number of tracks must be >18 and <=%i (block_size-0x38)/2\n\n",
|
||||
(block_size-0x38)/2);
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
/* sector_size 256->65536 (or 512 basedon one bye t/s size field?) */
|
||||
if ((block_size<256)||(block_size>65536)) {
|
||||
printf("Block size must be >=256 and <65536\n\n");
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
|
||||
buffer=calloc(1,sizeof(char)*block_size);
|
||||
|
||||
/* Open device */
|
||||
fd=open(device,O_WRONLY|O_CREAT,0666);
|
||||
if (fd<0) {
|
||||
fprintf(stderr,"Error opening %s\n",device);
|
||||
goto end_of_program;
|
||||
}
|
||||
|
||||
/* zero out file */
|
||||
for(i=0;i<num_tracks*num_sectors;i++) {
|
||||
write(fd,buffer,block_size);
|
||||
}
|
||||
|
||||
/* 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++) {
|
||||
read(dos_fd,buffer,block_size);
|
||||
write(fd,buffer,block_size);
|
||||
}
|
||||
close(dos_fd);
|
||||
|
||||
}
|
||||
|
||||
/* clear buffer */
|
||||
for(i=0;i<block_size;i++) buffer[i]=0;
|
||||
|
||||
/* Create VTOC */
|
||||
buffer[VTOC_DOS_RELEASE]=0x3; /* fake dos 3.3 */
|
||||
buffer[VTOC_CATALOG_T]=17;
|
||||
buffer[VTOC_CATALOG_S]=1; /* 1st Catalog typically at 0x11/0x1 */
|
||||
buffer[VTOC_DISK_VOLUME]=254; /* typical volume 254 */
|
||||
buffer[VTOC_MAX_TS_PAIRS]=((block_size-0xc)/2)&0xff;
|
||||
/* Number of T/S pairs fitting */
|
||||
/* in a T/S list sector */
|
||||
/* Note, overflows if block_size>524 */
|
||||
buffer[VTOC_LAST_ALLOC_T]=18; /* last track space was allocated */
|
||||
/* Start at middle, work way out */
|
||||
buffer[VTOC_ALLOC_DIRECT]=1; /* Working our way outward */
|
||||
buffer[VTOC_NUM_TRACKS]=num_tracks;
|
||||
buffer[VTOC_S_PER_TRACK]=num_sectors;
|
||||
buffer[VTOC_BYTES_PER_SL]=block_size&0xff;
|
||||
buffer[VTOC_BYTES_PER_SH]=(block_size>>8)&0xff;
|
||||
|
||||
/* Set sector bitmap so whole disk is free */
|
||||
for(i=VTOC_FREE_BITMAPS;i<block_size;i+=4) {
|
||||
buffer[i]=0xff;
|
||||
buffer[i+1]=0xff;
|
||||
if (num_sectors>16) {
|
||||
buffer[i+2]=0xff;
|
||||
buffer[i+3]=0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* reserve track 0 */
|
||||
/* No user data can be stored here as track=0 is special case */
|
||||
/* end of file indicator */
|
||||
buffer[VTOC_FREE_BITMAPS]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+1]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+2]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+3]=0x00;
|
||||
|
||||
if (copy_dos) {
|
||||
buffer[VTOC_FREE_BITMAPS+4]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+5]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+6]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+7]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+8]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+9]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+10]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+11]=0x00;
|
||||
}
|
||||
|
||||
/* reserve track 17 */
|
||||
/* reserved for vtoc and catalog stuff */
|
||||
buffer[VTOC_FREE_BITMAPS+17*4]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+17*4+1]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+17*4+2]=0x00;
|
||||
buffer[VTOC_FREE_BITMAPS+17*4+3]=0x00;
|
||||
|
||||
|
||||
|
||||
/* Write out VTOC to disk */
|
||||
lseek(fd,((17*num_sectors)+0)*block_size,SEEK_SET);
|
||||
write(fd,buffer,block_size);
|
||||
|
||||
|
||||
|
||||
|
||||
close(fd);
|
||||
|
||||
end_of_program:
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user