diff --git a/CHANGES b/CHANGES new file mode 100644 index 00000000..29c1503a --- /dev/null +++ b/CHANGES @@ -0,0 +1,24 @@ +1 May 2003 + +RELEASE 0.0.2 + +1 June 2003 + +RELEASE 0.0.4 + +21 June 2003 ++ Fix error where we could allocate a used sector! ARGH! + +RELEASE 0.0.5 + +18 July 2004 ++ Minor bug fix + +RELEASE 0.0.6 + +19 August 2007 ++ Fix so compiles with newish gcc ++ Update asoft_detoken to match documentation found online ++ Create tokenize_asoft + +RELEASE 0.0.7 diff --git a/Changelog b/Changelog deleted file mode 100644 index 423be330..00000000 --- a/Changelog +++ /dev/null @@ -1,2 +0,0 @@ -21 June 2003 -+ Fix error where we could allocate a used sector! ARGH! diff --git a/Makefile b/Makefile index 83f818bc..80fe49a6 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC = gcc C_FLAGS = -O2 -Wall L_FLAGS = -all: dos33 asoft_detoken mkdos33fs make_b +all: dos33 asoft_detoken mkdos33fs make_b tokenize_asoft @@ -12,7 +12,11 @@ asoft_detoken: asoft_detoken.o asoft_detoken.o: asoft_detoken.c $(CC) $(C_FLAGS) -c asoft_detoken.c +tokenize_asoft: tokenize_asoft.o + $(CC) $(L_FLAGS) -o tokenize_asoft tokenize_asoft.o +tokenize_asoft.o: tokenize_asoft.c + $(CC) $(C_FLAGS) -c tokenize_asoft.c dos33: dos33.o $(CC) $(L_FLAGS) -o dos33 dos33.o @@ -35,7 +39,7 @@ mkdos33fs.o: mkdos33fs.c dos33.h install: - cp dos33 asoft_detoken mkdos33fs make_b /usr/local/bin + cp dos33 asoft_detoken mkdos33fs tokenize_asoft make_b /usr/local/bin clean: - rm -f *~ *.o asoft_detoken dos33 make_b mkdos33fs + rm -f *~ *.o asoft_detoken dos33 make_b mkdos33fs tokenize_asoft diff --git a/README b/README new file mode 100644 index 00000000..ca9b3d83 --- /dev/null +++ b/README @@ -0,0 +1,19 @@ +dos33fsprogs + + by Vince Weaver + + +These are some tools for manipulating Apple II disk files that +I've written over the years while doing Apple 2 hacking. + +make_b : take a machine language blob and give it the size/offset + header needed to BLOAD it from DOS3.3 + +asoft_detoken: takes an applesoft file obtained with dos33 + and converts it to an ASCII text file + +tokenize_asoft: takes an ASCII text file and converts it + into a tokenized applesoft file + +dos33: a tool for manipulating dos33 .dsk images + diff --git a/TODO b/TODO index d1bef099..d67ba3b6 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,5 @@ defrag utility test-suite test mkdosfs copy over DOS functionality + +find out why dos33 SAVE puts extra linefeed at end of basic prog? diff --git a/asoft_detoken.c b/asoft_detoken.c index 4f7cce7a..3509e4e4 100644 --- a/asoft_detoken.c +++ b/asoft_detoken.c @@ -22,130 +22,36 @@ char applesoft_tokens[][8]={ /* F8 */ "","","","","","(","(","(" }; -/* -Integer Basic +#if 0 +/* 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 # - -*/ +char integer_tokens[][8]={ +/* 00 */ "","","",":","LOAD","SAVE","","RUN", +/* 08 */ "","DEL",",","NEW","CLR","AUTO","","MAN", +/* 10 */ "HIMEM:","LOMEM:","+","-","*","/","=","#", +/* 18 */ ">=",">","<=","<>","<"," AND"," OR"," MOD", +/* 20 */ "^","","(",",",""," THEN","",",", +/* 28 */ "\"","\"","(","","","("," PEEK","RND", +/* 30 */ "SGN","ABS","PDL","","(","+","-","NOT", +/* 38 */ "(","=","LEN (","ASC (","SCRN (",","," (", +/* 40 */ "$","(","",",","","",";", +/* 48 */ "",",",",","TEXT","GR","CALL","","DIM", +/* 50 */ "TAB","END","","","INPUT","FOR","=","TO", +/* 58 */ " STEP","NEXT",",","RETURN","GOSUB","REM","LET","GOTO", +/* 60 */ "IF","","PRINT","PRINT"," POKE",",","COLOR=","PLOT", +/* 68 */ ",","HLIN",","," AT","VLIN",","," AT","VTAB", +/* 70 */ "","=",")","","LIST",",","","POP", +/* 78 */ "","NO DSP","NO TRACE","","DSP","TRACE","PR #","IN #" +}; +#endif int main(int argc, char **argv) { int ch1,i; - unsigned char size1,size2; - unsigned char line1,line2; - unsigned char eight,line_length; + int size1,size2; + int line1,line2; + int link1,link2,link; /* read size, first two bytes */ @@ -153,17 +59,24 @@ int main(int argc, char **argv) { size2=fgetc(stdin); while(!feof(stdin)) { - + + /* link points to the next line */ + /* assumes asoft program starts at address $801 */ + link1=fgetc(stdin); + link2=fgetc(stdin); + link=(link1<<8)|link2; + /* link==0 indicates EOF */ + if (link==0) goto the_end; - line_length=fgetc(stdin); - eight=fgetc(stdin); /* sometimes 8, sometimes 9? */ - if (eight==0) goto the_end; + /* line number is little endian 16-bit value */ line1=fgetc(stdin); line2=fgetc(stdin); if (feof(stdin)) goto the_end; - printf("%4d ",(((int)line2)<<8)+line1); - + printf("%4d ",((line2)<<8)+line1); + + /* repeat until EOL character (0) */ while( (ch1=fgetc(stdin))!=0 ) { + /* if > 0x80 it's a token */ if (ch1>=0x80) { fputc(' ',stdout); for(i=0;i +#include /* strlen() */ +#include /* exit() */ + +/* TODO */ +/* match lowecase tokens as well as upper case ones */ + + + +/* Info from http://docs.info.apple.com/article.html?coll=ap&artnum=57 */ + +/* In memory, applesoft file starts at address $801 */ +/* format is $00$00 */ +/* Where is: */ +/* 2 bytes (little endian) of LINK indicating addy of next line */ +/* 2 bytes (little endian) giving the line number */ +/* a series of bytes either ASCII or tokens (see below) */ +/* a $0 char indicating end of line */ + + + /* 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 */ "","","","","","(","(","(" +}; + +#if 0 +/* Integer Basic */ + +char integer_tokens[][8]={ +/* 00 */ "","","",":","LOAD","SAVE","","RUN", +/* 08 */ "","DEL",",","NEW","CLR","AUTO","","MAN", +/* 10 */ "HIMEM:","LOMEM:","+","-","*","/","=","#", +/* 18 */ ">=",">","<=","<>","<"," AND"," OR"," MOD", +/* 20 */ "^","","(",",",""," THEN","",",", +/* 28 */ "\"","\"","(","","","("," PEEK","RND", +/* 30 */ "SGN","ABS","PDL","","(","+","-","NOT", +/* 38 */ "(","=","LEN (","ASC (","SCRN (",","," (", +/* 40 */ "$","(","",",","","",";", +/* 48 */ "",",",",","TEXT","GR","CALL","","DIM", +/* 50 */ "TAB","END","","","INPUT","FOR","=","TO", +/* 58 */ " STEP","NEXT",",","RETURN","GOSUB","REM","LET","GOTO", +/* 60 */ "IF","","PRINT","PRINT"," POKE",",","COLOR=","PLOT", +/* 68 */ ",","HLIN",","," AT","VLIN",","," AT","VTAB", +/* 70 */ "","=",")","","LIST",",","","POP", +/* 78 */ "","NO DSP","NO TRACE","","DSP","TRACE","PR #","IN #" +}; +#endif + +#define LOW(_x) ((_x)&0xff) +#define HIGH(_x) (((_x)>>8)&0xff) +#define MAXSIZE 65535 + +/* File cannot be longer than 64k */ +unsigned char output[MAXSIZE+1]; + +char *line_ptr; +int line=0; +char input_line[BUFSIZ]; + +static void show_problem(char *line_ptr) { + int offset,i; + + offset=(int)(line_ptr-input_line); + fprintf(stderr,"%s",input_line); + for(i=0;i' ') { + if ((*line_ptr<'0')||(*line_ptr>'9')) { + fprintf(stderr,"Invalid line number line %d\n",line); + show_problem(line_ptr); + exit(-1); + } + num*=10; + num+=(*line_ptr)-'0'; + line_ptr++; + } + + if (!line_ptr) { + fprintf(stderr,"Missing line number line %d\n",line); + exit(-1); + } + + return num; +} + +static int in_quotes; + +static int find_token() { + + int ch,i; + + ch=*line_ptr; + /* don't skip whitespace in quotes */ + if (!in_quotes) { + while(ch<=' ') { + if ((ch=='\n') || (ch=='\r') || (ch=='\0')) { + return 0; + } + line_ptr++; + ch=*line_ptr; + } + } + + + /* toggle quotes mode */ + if (ch=='\"') in_quotes=!in_quotes; + + /* don't tokenize if in quotes */ + if (!in_quotes) { + + // fprintf(stderr,"%s",line_ptr); + for(i=0;i<107;i++) { + if (!strncmp(line_ptr,applesoft_tokens[i],strlen(applesoft_tokens[i]))) { +// fprintf(stderr,"Found token %x (%s) %d\n",0x80+i,applesoft_tokens[i],i); + line_ptr+=strlen(applesoft_tokens[i]); + return 0x80+i; + } +// fprintf(stderr,"%s ",applesoft_tokens[i]); + } + } + +// fprintf(stderr,"\n"); + /* not a token, just ascii */ + line_ptr++; + return ch; +} + +static void check_oflo(int size) { + if (size>MAXSIZE) { + fprintf(stderr,"Output file too big!\n"); + exit(-1); + } +} + + + + +int main(int argc, char **argv) { + + int offset=2,i; + + int linenum,link_offset; + int link_value=0x801; /* start of applesoft program */ + int token; + + while(1) { + /* get line from input file */ + line_ptr=fgets(input_line,BUFSIZ,stdin); + line++; + if (line_ptr==NULL) break; + linenum=getnum(); + if (linenum>65535) { + printf("Invalid line number %d\n",linenum); + exit(-1); + } + link_offset=offset; + check_oflo(offset+4); + output[offset+2]=LOW(linenum); + output[offset+3]=HIGH(linenum); + offset+=4; + + + while(1) { + token=find_token(); + output[offset]=token; + offset++; + check_oflo(offset); + if (!token) break; + } + + + /* 2 bytes is to ignore size from beginning of file */ + link_value=0x801+(offset-2); + + /* point link value to next line */ + check_oflo(offset+2); + output[link_offset]=LOW(link_value); + output[link_offset+1]=HIGH(link_value); + } + /* set last link field to $00 $00 which indicates EOF */ + check_oflo(offset+2); + output[offset]='\0'; + output[offset+1]='\0'; + offset+=2; + + /* Set filesize */ + /* -1 to match observed values */ + output[0]=LOW(offset-1); + output[1]=HIGH(offset-1); + /* output our file */ + for(i=0;i