.TITLE COD - (en)code/(de)code .LIBRARY /[1,1]EXEMC.MLB/ .INCLUDE /[11,10]RSXMC.MAC/ .IDENT /V1.4/ ; + ; Encode/Decode program for RSX. ; ; (c) 1996 by Johnny Billquist ; ; X0.0 18-Nov-96 01:00 BQT Initial coding started. ; Y1.0 19-Nov-96 01:20 BQT First working version. ; Y1.1 19-Nov-96 03:15 BQT Bugfix. ; Y1.2 19-Nov-96 22:00 BQT Speed enhancements. ; V1.3 24-Nov-96 04:30 BQT Added additional line handling. ; V1.4 11-Dec-96 07:00 BQT Expanded command line logic. ; Bugfix which added more speed. ; - .MCALL LBLDF$ .MCALL GCMLB$, GCML$, CSI$, CSI$1, CSI$4, CSI$SW, CSI$SV, CSI$ND .MCALL QIOW$S, EXIT$S, ALUN$S, GTIM$S, WTSE$S .MCALL FSRSZ$, FINIT$, FDBDF$, FDAT$A, FDRC$A, FDOP$A, NMBLK$ .MCALL FDAT$R, FDRC$R, FDBF$R, FDBK$R, WAIT$, DELET$ .MCALL OPEN$R, OPEN$W, GET$, PUT$, CLOSE$, READ$, WRITE$ ; MAXRPT=256. ; Maximum number of repeats. RPTCHR='= ; Repeat indication character. BUFLEN=2560. ; Buffer length. MAXWAT=5 ; Maximum number of attributes we can write. MAXBUF=4 ; Multibuffer number. ; .PSECT CMDR,D,RO ; INSWT: CSI$SW EN,1,CMASK,SET,NEG CSI$SW DE,1,CMASK,CLEAR,NEG CSI$SW ID,2,CMASK,SET CSI$SW WI,4,CMASK,SET,,WIVAL CSI$SW HE,10,CMASK,SET CSI$SW NM,20,CMASK,SET CSI$ND ; WIVAL: CSI$SV DECIMAL,MAXWID,2 CSI$ND ; .MACRO MULT .IF DF R$$EIS MUL R1,R0 .IFF CALL $MUL .ENDC .ENDM .MACRO DIVV .IF DF R$$EIS MOV R2,-(SP) MOV R1,R2 MOV R0,R1 CLR R0 DIV R2,R0 MOV (SP)+,R2 .IFF CALL $DIV .ENDC .ENDM ; TILUN=1 INLUN=2 OUTLUN=3 CMLUN=4 ; TIEFN=1 INEFN1=11 INEFN2=12 OUTEF1=21 OUTEF2=22 ; LBLDF$ FSRSZ$ 1,512.+ ; .PSECT CODE,I,RO ; START: MOV R3,VER ; Save program version. MOV R4,VER+2 ALUN$S #TILUN,#"TI,#0 ; Assign TI0: ALUN$S #CMLUN,#"TI,#0 MOV SP,SAVSP ; ; The main program loop. ; LOOP: MOV SAVSP,SP FINIT$ ; Initialize FCS. GCML$ #CMLB ; Get a command. BCC 10$ ; Okay... EXIT$S ; Time to exit. ; 10$: CSI$1 #CSIBLK,CMLB+G.CMLD+2,CMLB+G.CMLD ; Parse command. BCC 20$ ; Okay... QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#PETXT,#PELEN,#'$> ; Error. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,, BR LOOP ; 20$: TST CSIBLK+C.CMLD ; Anything to parse? BEQ LOOP ; Nope. CLR CMASK ; Set default action. MOV #24.,MAXWID ; Set deault width. BITB #CS.EQU,CSIBLK+C.STAT ; Any output specified? BNE 21$ ; Yes. CSI$4 #CSIBLK,OUTPUT,#INSWT ; No. Parse output as input. BR 22$ ; 21$: CSI$4 #CSIBLK,INPUT,#INSWT ; Parse input. 22$: BCC 30$ ; Okay. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#PIETXT,#PIELEN,#40> ; Error. JMP LOOP ; 30$: BITB #CS.MOR,CSIBLK+C.STAT ; More files specified? BEQ 40$ ; No. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#MIETXT,#MIELEN,#40> ; Error. JMP LOOP ; ; Now we have parsed the input file name. ; CMASK also holds what action we shall do. ; 40$: BIT #10,CMASK ; Help? BEQ 41$ ; No. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#HLPMSG,#HLPLEN,#40> JMP LOOP ; 41$: BIT #2,CMASK ; ID? BEQ 43$ ; No. MOV #BUF,R0 ; Yes. MOV #V2FMT,R1 MOV #VER,R2 CALL $EDMSG SUB #BUF,R0 QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#BUF,R0,#40> JMP LOOP 43$: BIT #4,CMASK ; Width? BEQ 42$ ; No. MOV MAXWID,R0 ; Yes. SUB #5,R0 ; Lenght without <> and 3 chars... CMP R0,#3 ; Must be atleast 3 chars... BLO 410$ ; No room in line. MOV #3,R1 DIVV ; Find out words/line. MOV R0,MAXWID ; There. 42$: ; MOV #^RENC,INDFN+N.FTYP ; Default file type. MOV #-1,R1 CALL .WDFFP ; Set default protection. ; BIT #1,CSIBLK+C.MKW1 ; Was action switch specified? BEQ 45$ ; No. BIT #1,CMASK ; Shall we encode? BEQ DECODE ; Nope. JMP ENCODE ; Yes. ; 45$: MOV #FDBIN,R0 ; Setup for a parse of filename. MOV #FDBIN+F.FNB,R1 MOV #CSIBLK+C.DSDS,R2 MOV #INDFN,R3 CALL .PRSFN ; Parse filename. CMP #^RENC,FDBIN+F.FNB+N.FTYP ; Extension of "ENC"? BEQ DECODE ; Yes. Decode. JMP ENCODE ; No. Encode. ; ; Too narrow for output... ; 410$: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#WNERR,#WNELEN,#40> JMP LOOP ; ; This is the decode routine. It's pretty straight forward. ; DECODE: ; ; Start by setting up relevant information for the input file, ; and open it. ; FDRC$R #FDBIN,#FD.PLC,#INBUF1,#BUFLEN FDBF$R #FDBIN,#INEFN1,#BUFLEN,#MAXBUF,#FD.RAH OPEN$R #FDBIN,,,,,,ENCODE ; Open input. ; ; Now we'll read stuff from the input file. ; The format of a proper encoded file is that first there may come ; unspecified lines, then we should get a line saying: ; "(START)". This means it's time to start parsing stuff. ; 10$: GET$ #FDBIN,,,DEERR2 ; Get data. JSR R5,PARSE ; Try to parse line. .WORD P1TAB ; Parse table. .WORD FDBIN+F.NRBD+2 ; Pointer to string. .WORD FDBIN+F.NRBD ; Length of string. BCS 10$ ; CS means no match was found. ; ; Now we have found the first line. Let's parse stuff. ; ; (Well, first we'll set up some defaults...) ; MOV FDBIN+F.FNB+N.FNAM,OUTDFN+N.FNAM ; Set default name MOV FDBIN+F.FNB+N.FNAM+2,OUTDFN+N.FNAM+2 ; block... MOV FDBIN+F.FNB+N.FNAM+4,OUTDFN+N.FNAM+4 MOV #^RXXX,OUTDFN+N.FTYP ; .XXX;0 CLR OUTDFN+N.FVER MOV FDBIN+F.FNB+N.DVNM,OUTDFN+N.DVNM MOV FDBIN+F.FNB+N.UNIT,OUTDFN+N.UNIT MOV #WATBLK,WATPTR ; Set pointer to attribute list. CLR WATCNT ; No items added so far. CLR WATBLK ; Mark end of list. CLR FILSIZ ; Clear requested filesize. CLR FCHAR ; Clear contigous flag. ; 20$: GET$ #FDBIN,,,DEERR3 ; Get next line of data. JSR R5,PARSE ; Try to parse line. .WORD P2TAB ; Parse table. .WORD FDBIN+F.NRBD+2 ; String pointer. .WORD FDBIN+F.NRBD ; Pointer to string length. BCC 30$ ; We found a match. CMPB #'(,@FDBIN+F.NRBD+2 ; Does it start with a '('? BNE 25$ ; Nope. BIT #20,CMASK ; No message? BNE 20$ ; Yep. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#BF,#BFLEN,#'$> ; Bad line. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,, BR 20$ ; Loop. 25$: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#IL,#ILLEN,#'$> QIOW$S #IO.WLB,#TILUN,#TIEFN,,,, JMP CLSIN 30$: CALL (R0) ; Call proper handler. BCC 20$ ; CS means we shall exit this loop. ; ; Now it's time to open the output file. ; By now we have some useful information set up in the FDB. ; TST FCHAR ; Shall we be contig? BEQ 35$ ; No. NEG FILSIZ ; Yes. 35$: FDAT$R #FDBOUT,,,,FILSIZ ; Set filesize. CSI$4 #CSIBLK,OUTPUT ; Parse output. BCC 40$ ; Okay. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#POETXT,#POELEN,#40> ; Error. JMP CLSIN ; Close input file. ; 40$: BITB #CS.MOR,CSIBLK+C.STAT ; More files specified? BEQ 50$ ; No. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#MOETXT,#MOELEN,#40> ; Yes. Error. JMP CLSIN ; Close input file. ; ; Now we have set most things up. However, we need to fix a few final ; things... ; 50$: FDRC$R #FDBOUT,#FD.RWM FDBK$R #FDBOUT,#OUTBF1,#BUFLEN,,#OUTEF1,#OUTSB1 OPEN$W #FDBOUT,,,,,,DEERR5 ; ; Here we should decode the input file, and write the stuff ; to the output file. ; CALL DEINIT ; Initialize decoder. MOV #OUTBF1,R5 ; Setup registers for saving stuff. MOV #BUFLEN/2,R4 110$: CALL RDDEWD ; Get a word. BCS 1000$ ; Error. We'll assume EOF then. MOV R1,(R5)+ ; Save word. ADD R1,CKSUM ; Calculate checksum. SOB R4,110$ ; And repeat. ; CALL WRBLK ; Output block. BR 110$ ; And loop. ; ; When we are done, we'll do some final stuff... ; 1000$: BIT #255.,R4 ; Are we in the middle of a block? BNE 1020$ ; Error. CALL WRBLK ; Output last block. JSR R5,PARSE ; Try to parse line. .WORD P3TAB ; Parse table. .WORD FDBIN+F.NRBD+2 ; String pointer. .WORD FDBIN+F.NRBD ; Pointer to string length. BCC 1010$ ; Check. ; QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#BF,#BFLEN,#'$> ; Bad line. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,, DELET$ #FDBOUT,DEERR7 ; Remove result. JMP CLSIN ; Done. ; 1010$: MOV STRPTR,R0 ; Get string pointer. CALL $COTB ; Convert checksum to binary. CMPB R2,#') ; Terminator should be ') BNE 1020$ ; Weirdo. ADD CKSUM,R1 ; Check checksum. COM R1 ; Complement should be zero. BNE 1020$ ; ; Okay. The file integrity is pretty good. Now we can try to fix ; the file header. ; TST WRFLG ; Have we written anything? BEQ 1011$ ; No. WAIT$ #FDBOUT,,,DEERR6 ; Wait for last write. 1011$: MOV #FDBOUT,R0 ; Setup for writing attrs. MOV #IO.DAC,R1 MOV #2,R2 MOV #IOPLO,R3 CALL .XQIO ; Write attributes. ; CLR FDBOUT+F.FNB+N.FID JMP DONE ; Done. ; 1020$: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#CKERR,#CKELEN,#40> DELET$ #FDBOUT,DEERR7 JMP CLSIN ; ; Write a block. ; WRBLK: SUB #BUFLEN/2,R4 ; Calculate output length. NEG R4 BEQ 30$ ; No data to output. MOV R4,WRFLG ; Set flag. ASL R4 ; Make size in bytes. ADD WRSTAT,PC ; Jump to proper routine. BR 10$ BR 11$ BR 12$ ; ; Mode 1. Write even. ; 11$: WRITE$ #FDBOUT,#OUTBF1,R4,,#OUTEF1,#OUTSB1,,DEERR6 MOV #OUTBF2,R5 MOV #4,WRSTAT WTSE$S #OUTEF2 CMPB OUTSB2,#IS.SUC BEQ 20$ JMP DEERR6 ; ; Mode 0. Writing first block. ; 10$: WRITE$ #FDBOUT,#OUTBF1,R4,,#OUTEF1,#OUTSB1,,DEERR6 MOV #OUTBF2,R5 MOV #4,WRSTAT BR 20$ ; ; Mode 2. Write odd. ; 12$: WRITE$ #FDBOUT,#OUTBF2,R4,,#OUTEF2,#OUTSB2,,DEERR6 MOV #OUTBF1,R5 MOV #2,WRSTAT WTSE$S #OUTEF1 CMPB OUTSB1,#IS.SUC BEQ 13$ JMP DEERR6 13$: 20$: MOV #BUFLEN/2,R4 30$: RETURN ; DEERR1: JSR R5,EXPFN ; Expand filename proper. .WORD FDBIN+F.FNB+N.FNAM ; From here. .WORD FNBUF ; To here. MOV #FNBUF,ARGBLK ; Format error message. MOV #BUF,R0 MOV #IOERR,R1 MOV #ARGBLK,R2 CALL $EDMSG SUB #BUF,R0 QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#BUF,R0,#40> ; Print it. JMP LOOP ; And loop. DEERR2: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#INOHD,#INHLEN,#40> JMP CLSIN DEERR3: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#IBADHD,#IBHLEN,#40> JMP CLSIN DEERR5: JSR R5,EXPFN ; Expand filename proper. .WORD FDBOUT+F.FNB+N.FNAM ; From here. .WORD FNBUF ; To here. MOV #FNBUF,ARGBLK ; Format error message. MOV #BUF,R0 MOV #OOERR,R1 MOV #ARGBLK,R2 CALL $EDMSG SUB #BUF,R0 QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#BUF,R0,#40> ; Print it. JMP LOOP ; And loop. DEERR6: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#OWERR,#OWELEN,#40> DELET$ #FDBOUT,DEERR7 JMP CLSIN DEERR7: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#DELERR,#DELEN,#40> JMP ABRT ; ; Parser routines. ; ; SETNAM - Handle filename. ; SETNAM: CALL $SAVAL ; Save registers. BIT #20,CMASK ; No message? BNE 1$ ; Yep. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,, 1$: MOV STRPTR,R0 ; Get pointer to string. MOV STRLEN,R1 ; Get length of string. ADD R0,R1 ; Get pointer to first free char. MOV #OUTDFN+N.FNAM,R3 ; Destination. MOV #3,R4 ; 3 words... 10$: CLR R1 ; '.' is not acceptable. CALL $CAT5 ; Convert characters. MOV R1,(R3)+ ; Save characters. BCC 15$ ; Okay. DEC R0 ; Error. Redo char. 15$: SOB R4,10$ ; Loop. ; 20$: CMPB (R0)+,#'. ; Look for period. BNE 20$ ; CLR R1 ; '.' is not acceptable. CALL $CAT5 ; Convert. MOV R1,(R3)+ ; Save extension. CLC ; Don't abort. RETURN ; Done. ; ; DOREM - Do remark. ; DOREM: BIT #20,CMASK ; No message? BNE 10$ ; Yep. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,, 10$: CLC RETURN ; ; SETATT - Do Files11 header. ; ; No registers are modified. ; SETATT: CALL $SAVAL ; Save registers. MOV STRPTR,R0 ; Set read pointer. CMP STRLEN,#40 ; Check read length. BLO 100$ ; Bad. MOV #FATT,R2 ; Pointer to destination area. MOV #40/2,R3 ; # of words expected. 10$: CALL DECWRD ; Decode word. BCS 100$ ; Error. MOV R1,(R2)+ ; Save word. SOB R3,10$ ; Repeat. ; MOV WATPTR,R0 ; Get write attribute ptr. CMP WATCNT,#MAXWAT ; Max # of items already. BHIS 100$ ; Already max. Don't add item. INC WATCNT ; Bump item count. MOV #<40*400>+4,(R0)+ ; Save function and size. MOV #FATT,(R0)+ ; Pointer. CLR (R0) ; Mark end. MOV R0,WATPTR ; Save new pointer. RETURN ; Done. ; 100$: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#ATTERR,#ATTLEN,#40> JMP TELLIN ; ; SETSIZ - Set file size. ; ; No registers modified. ; SETSIZ: CALL $SAVAL ; Save registers. MOV STRPTR,R5 ; Get pointer to string. MOV R5,R4 ; Copy string pointer. 10$: CMPB (R4)+,#') ; Look for end of number. BNE 10$ SUB R5,R4 ; Calculate length. DEC R4 ; Remove end marker. MOV #INISB1,R3 ; Destination. CALL .DD2CT ; Get size. BCS 20$ ; Error. Ignore. TST INISB1 ; High order set? BNE 20$ ; Yes. Can't be contig. TST INISB1+2 ; Negative? BMI 20$ ; Yes. Can only handle 15-bits. MOV INISB1+2,FILSIZ ; Save filesize. NEG FILSIZ ; Not contigous by default. 20$: CLC ; No errors returned. RETURN ; ; SETPRO - Set file protection. ; SETPRO: CALL $SAVAL ; Save registers. MOV STRPTR,R0 ; Get string pointer. CALL $COTB ; Convert number. CMPB R2,#') ; Expected end. BNE 10$ ; Strange... MOV R1,FPROT ; Save new protection mask. BIC #^B11111111,R1 ; Allow all for owner and system... CALL .WDFFP ; Save it here too... CMP WATCNT,#MAXWAT ; Itemlist full? BHIS 20$ ; Yes. INC WATCNT ; No. Bump count. MOV WATPTR,R0 MOV #<2*400>+2,(R0)+ ; Save function and size. MOV #FPROT,(R0)+ ; Pointer to protection mask. MOV R0,WATPTR CLC ; No error. RETURN ; Done. ; 10$: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#BADEND,#BELEN,#40> JMP TELLIN ; 20$: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#ATTERR,#ATTLEN,#40> JMP TELLIN ; ; SETCNT - Set contigous. ; SETCNT: MOV #100000,FCHAR ; Set flag. RETURN ; Done. ; ; DODAT - Start data. ; DODAT: CLR RDLEN ; Clear input length. CLR CKSUM ; Clear checksum. SEC ; End parse loop. RETURN ; ; DEINIT - Initialize decoder engine. ; ; No registers are modified. ; DEINIT: CLR RPTCNT ; Clear repeat count. CLR CKSUM ; Clear checksum. CLR RDLEN ; Clear read length. CLR WRSTAT ; Clear write state. CLR WRFLG ; Clear flag indicating writing done. RETURN ; ; RDDEWD - Read decoded word ; ; In: - ; ; Out: CC: R1 - Character decoded. ; CS: EOF ; RDDEWD: TST RPTCNT ; Are we in a repeat? BEQ 10$ ; No. DEC RPTCNT ; Yes. Decrement repeat. MOV RPTWD,R1 ; Get repeat char. RETURN ; Done. ; 10$: MOV R0,-(SP) ; Save register. CMP RDLEN,#4 ; Less than 4 chars on line? BHIS 20$ ; No. 15$: CALL RDLIN ; Yes. Read a new line. BCS 40$ ; Abort. 20$: MOV RDPTR,R0 ; Get read pointer. CALL DECWRD ; Decode word. BCS 30$ ; Didn't work. Try to find out why. MOV R0,RDPTR ; Worked fine. Save new pointer. SUB #3,RDLEN ; And drop stuff from length. MOV (SP)+,R0 ; Restore R0. CLC ; Clear error. RETURN ; Done. ; ; For some reason, we couldn't decode the next three chars. ; Let's see why... ; 30$: CMPB (R0),#'> ; End of line? BEQ 15$ ; Yes. Fetch new line. CMPB (R0),#RPTCHR ; Repeat prefix? BEQ 35$ ; Yes. ; ; Weird data. Abort abort... ; 31$: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#CORDAT,#CDLEN,#40> DELET$ #FDBOUT,DEERR7 JMP TELLIN ; ; Repeat time. ; 35$: INC R0 ; Bump past repeat char. CALL 100$ ; Get first nybble. .REPT 4 ASL R1 ; Move to high part. .ENDR MOV R1,RPTCNT CALL 100$ ; Get second nybble. ADD R1,RPTCNT ; Now we have full repeat count. CALL DECWRD ; Now, decode next word. BCS 31$ ; Weird! MOV R1,RPTWD ; Save repeat word. MOV R0,RDPTR ; Save read pointer. SUB #6,RDLEN ; And remove the length handled. MOV (SP)+,R0 ; Restore R0. CLC ; No error. RETURN ; Done. This was easy... ; ; We "failed" to read a new line. ; Could be many things. Let someone else handle it. ; 40$: MOV (SP)+,R0 ; Restore R0. SEC RETURN ; ; Fetch a HEX nybble. ; 100$: CLR R1 ; Get character. BISB (R0)+,R1 SUB #'0,R1 ; Make it binary. CMP R1,#10. ; Was it alpha? BLO 110$ ; No. SUB #7,R1 ; Yes. Additional correction. 110$: RETURN ; Done. ; ; RDLIN - Read line from input file. ; ; No registers are modified. ; Any error means we'll return with carry set. ; RDLIN: MOV R0,-(SP) ; Save registers. MOV R1,-(SP) MOV R2,-(SP) GET$ #FDBIN ; Get line. BCS 20$ ; Error. ; MOV FDBIN+F.NRBD+2,R1 ; Get string pointer. MOV FDBIN+F.NRBD,R2 ; Get length. CALL UPCASE ; Make into uppercase. MOV #'<,R0 ; Character to look for. CALL FNDCHR ; Find character. BCC 20$ ; Not start of data. Error. TST R2 ; No more on line? BEQ 20$ ; No more. Error. DEC R2 ; Decrement length by one. INC R1 ; Skip past start char. CMP R2,#4 ; We must have atleast 4 bytes left. BLO 20$ ; Error. MOV R1,RDPTR ; Save pointer. MOV R2,RDLEN ; Okay. MOV (SP)+,R2 ; Restore registers. MOV (SP)+,R1 MOV (SP)+,R0 CLC ; We are set to go. RETURN ; 20$: MOV (SP)+,R2 ; Restore registers. MOV (SP)+,R1 MOV (SP)+,R0 SEC ; Error. RETURN ; Done. ; ; Parser. ; ; In: (R5) - Parse table. ; 2(R5) - Address of address of input string. ; 4(R5) - Address of length of input string. ; ; Out: CS - No match was found. ; CC - Match was found. R0 match result. ; ; The parse table is pretty simple. ; It is a series of doublewords. The first word points ; to a nul-terminated string, and the second word is ; the match result. ; ; All other registers are preserved. ; PARSE: MOV R1,-(SP) ; Save registers. MOV R2,-(SP) MOV R3,-(SP) MOV (R5)+,R0 ; Get parse table pointer. MOV @(R5)+,R1 ; String pointer. MOV @(R5)+,R2 ; String length. CALL UPCASE ; Convert string to uppercase. MOV R0,-(SP) ; Save R0. MOV #'(,R0 ; Look for start of command. CALL FNDCHR ; Look out. MOV (SP)+,R0 ; And restore R0. BCC 30$ ; No start found. ; 10$: MOV (R0)+,R3 ; Get next parse string. BEQ 30$ ; End of table... CALL STRCMP ; Compare strings. BCS 20$ ; Match. TST (R0)+ ; No match. Take next. BR 10$ ; Loop. ; 20$: MOV (R0),R0 ; Get result word. CLC ; Indicate success. BR 40$ ; Done. ; 30$: SEC ; Indicate failure. 40$: MOV (SP)+,R3 ; Restore registers. MOV (SP)+,R2 MOV (SP)+,R1 RTS R5 ; Return. ; ; String uppercase. ; ; In: R1 - String pointer. ; R2 - String length. ; ; No registers are modified. ; UPCASE: MOV R1,-(SP) ; Save registers. MOV R2,-(SP) BEQ 30$ ; Zero-length string? 10$: CMPB (R1),#'a ; Char shall be a lowercase for this... BLO 20$ ; Not. CMPB (R1),#'z BHI 20$ BICB #40,(R1) ; It was. Remove lowercase. 20$: INC R1 ; Next char. SOB R2,10$ ; Loop. 30$: MOV (SP)+,R2 ; Restore registers. MOV (SP)+,R1 RETURN ; Done. ; ; STRCMP - Compare two strings. ; ; In: R1 - Address of string 1. ; R2 - Length of string 1. ; R3 - Address of string 2 (nul-terminated) ; ; Out: CC - Strings don't match. ; CS - Strings match. ; STRCMP: MOV R1,-(SP) ; Save registers. MOV R3,-(SP) MOV R2,-(SP) BEQ 90$ ; No match. 10$: TSTB (R3) ; End of matching string? BEQ 100$ ; Yes. We have a match. CMPB (R1)+,(R3)+ ; Characters equal? BNE 90$ ; Nope. No match. SOB R2,10$ ; Yes. Take next. ; ; String 1 terminated. If string 2 also terminates now, we are ok, ; otherwise we didn't match. ; TSTB (R3) ; End of string 2? BEQ 100$ ; Yes! ; ; No match. ; 90$: CLC ; Clear carry. BR 110$ ; And return. ; ; Match. ; 100$: MOV R1,STRPTR ; Save rest of string. MOV R2,STRLEN SEC ; Set carry. 110$: MOV (SP)+,R2 ; Restore registers. MOV (SP)+,R3 MOV (SP)+,R1 RETURN ; ; FNDCHR - Find a character. ; ; In: R0 - Character ; R1 - Pointer to string ; R2 - Length of string ; ; Out: CC: Character not found. R1,R2 undefined. ; CS: Character found. R1 points at character. ; R2 - Remaining length. ; FNDCHR: TST R2 ; No lenght? BEQ 20$ ; True. We fail. 10$: CMPB R0,(R1)+ ; This char? BEQ 30$ ; Yes. SOB R2,10$ ; No. Repeat. 20$: CLC ; Not found. Clear carry. RETURN 30$: DEC R1 ; Found. Backup. SEC ; Indicate this. RETURN ; Done. ; ; File encode... ; This routine will read a file, block by block, and ; code it as a text file. ; At the start of the file, some initial records will be ; inserted. ; ENCODE: ; ; Start by opening the input file. ; MOV #^RTSK,INDFN+N.FTYP ; Default file type. FDRC$R #FDBIN,#FD.RWM OPEN$R #FDBIN,,,,,,ENERR1 ; ; Next, let's read the attribute stuff. ; MOV #FDBIN,R0 MOV #IO.RAT,R1 MOV #2,R2 MOV #IOPLI,R3 CALL .XQIO ; Read attributes. ; MOV FPROT,R1 BIC #^B11111111,R1 ; Allow all for owner and system... CALL .WDFFP ; Save default prot. ; ; Next. Let's setup the stuff for the output file. ; MOV FDBIN+F.FNB+N.FNAM,OUTDFN+N.FNAM ; Set default name MOV FDBIN+F.FNB+N.FNAM+2,OUTDFN+N.FNAM+2 ; block... MOV FDBIN+F.FNB+N.FNAM+4,OUTDFN+N.FNAM+4 MOV #^RENC,OUTDFN+N.FTYP ; .ENC;0 CLR OUTDFN+N.FVER MOV FDBIN+F.FNB+N.DVNM,OUTDFN+N.DVNM MOV FDBIN+F.FNB+N.UNIT,OUTDFN+N.UNIT ; ; Time to open output file... ; CSI$4 #CSIBLK,OUTPUT ; Parse output. BCC 4$ ; Okay. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#POETXT,#POELEN,#40> ; Error. JMP CLSIN ; Close input file. ; 4$: BITB #CS.MOR,CSIBLK+C.STAT ; More files specified? BEQ 5$ ; No. QIOW$S #IO.WLB,#TILUN,#TIEFN,,,,<#MOETXT,#MOELEN,#40> ; Yes. Error. JMP CLSIN ; Close input file. ; ; Now we have set most things up. However, we need to fix a few final ; things... ; 5$: FDRC$R #FDBOUT,,#OUTBF1,#BUFLEN FDBF$R #FDBOUT,#OUTEF1,#BUFLEN,#MAXBUF,#FD.WBH FDAT$R #FDBOUT,#R.VAR,#FD.CR,,#200.,#100. OPEN$W #FDBOUT,,,,,,ENERR2 ; Open output. ; CALL ENINIT ; Initialize encode. CALL CRHDR ; Create header lines. BCC 10$ ; All good. JMP ENERR3 ; Couldn't create header lines. ; ; Time to encode the data in the file. ; 10$: CALL ENCLIN ; Encode line. TSTB CODBUF ; Got a result? BEQ ENCDON ; No. We are done. JSR R5,PUTSTR ; Yes. Output string. .WORD DATFMT .WORD 1 .WORD 0,CODBUF BCC 10$ ; And loop. ; BR ENERR3 ; ENCDON: COM CKSUM ; Complement checksum. JSR R5,PUTSTR .WORD ENDFMT .WORD 2 .WORD 0,ENDSTR .WORD 1,CKSUM BCS ENERR3 JMP DONE ; ENERR1: JMP DEERR1 ENERR2: JMP DEERR5 ENERR3: JMP DEERR6 ; ; When we are done, we'll come here... ; DONE: ABRT: CLOSE$ #FDBOUT CLSIN: CLOSE$ #FDBIN JMP LOOP ; ; TELLIN - Write out input buffer, and close files. ; TELLIN: QIOW$S #IO.WLB,#TILUN,#TIEFN,,,, JMP ABRT ; ; ENCLIN - Encode a line. ; ; This routine will read N words from the input file, and code ; them into CODBUF. ; ; Repeat count is also handled. ; ; No registers are modified. ; ENCLIN: CALL $SAVAL ; Save registers. MOV #CODBUF,R0 ; Destination pointer. CLR R4 ; Count of processed words. 10$: CALL RDWD ; Read word. BCS 50$ ; EOF... MOV R1,R2 ; Save word. CLR R3 ; Clear repeat count. 20$: CALL RDWD ; Get next word. INC R3 ; Bump repeat count. BCS 35$ ; EOF... CMP R3,#MAXRPT ; Max repeat? BEQ 30$ ; Yes. CMP R1,R2 ; Same word? BEQ 20$ ; Yes. Check next. ; ; Done with repeat. Unget last word, and decrement count by one. ; 30$: CALL UNRDWD ; Unget word. 35$: DEC R3 ; Decrement count. BEQ 40$ ; No repeat. Skip this part. ; ; We shall issue a repeat. We'll insert two words now. The first ; will be an illegal code word, with a count in the low two chars. ; The second word will be the word to repeat. ; INC R4 ; Bump output word count. MOVB #RPTCHR,(R0)+ ; Input repeat char. MOV R3,R1 ; Get count in R1. CALL PUTHEX ; Output hex. ; ; Now we'll output the actual word. ; 40$: INC R4 ; Bump output count. MOV R2,R1 ; Get word in R1. CALL ENCWRD ; Encode word. CMP R4,MAXWID ; Have we output enough? BLO 10$ ; Nope. 50$: CLRB (R0) ; Yes. Mark end. RETURN ; ; PUTHEX - Output a two-digit hex number. ; ; In: R0 - Points to buffer. ; R1 - Value ; ; Out: R0 - Points to next byte in buffer. ; ; No other registers are modified. ; PUTHEX: JSR R5,$SAVRG ; Save registers. MOVB R1,R3 ; First nybble. .REPT 4 ASR R3 .ENDR CALL 10$ ; Output first nybble. MOV R1,R3 ; Second nybble. 10$: BIC #^C17,R3 ; Clear all but significant bits. ADD #'0,R3 ; Make into ascii. CMP R3,#'9 ; Alpha digit? BLOS 20$ ; No. ADD #7,R3 ; Yes. 20$: MOVB R3,(R0)+ ; Save character. RETURN ; Done. ; ; RDWD - Read word. ; ; In: - ; ; Out: CC: R1 - Word read. ; CS: EOF ; RDWD: TST UNGETF ; Anything in the buffer? BEQ 10$ ; No. MOV UNGETC,R1 ; Yes. Get that. CLR UNGETF ; Clear flag. RETURN ; And we're done. ; 10$: TST RDLEN ; Anything currently in buffer? BEQ 1000$ ; No. JMP 20$ ; Yes. ; ; Buffer is empty. Let's read another block from disk. ; 1000$: MOV R0,-(SP) ; Save register. MOV #1010$,R0 ; Get state table. ADD RDSTAT,R0 ; Get current state. JMP @(R0) ; Jump to correct state. ; 1010$: .WORD 11$ .WORD 12$ .WORD 13$ .WORD 16$ ; ; Mode 3. EOF... ; 16$: MOV (SP)+,R0 ; Restore R0. SEC ; Error. RETURN ; ; Mode 0. Initial mode. Issue all reads, and wait for the first. ; 11$: READ$ #FDBIN,#INBUF1,#BUFLEN,,#INEFN1,#INISB1,,100$ ; ; Mode 1. Read next block, and wait for completion of first. ; 12$: MOV #4,RDSTAT ; Set mode to next. READ$ #FDBIN,#INBUF2,#BUFLEN,,#INEFN2,#INISB2,,100$ TSTB INISB1 ; Are we waiting for this operation? BNE 120$ ; No. WTSE$S #INEFN1 ; Yes. Wait... 120$: MOV INISB1+2,RDLEN ; Get length read. MOV #INBUF1,RDPTR ; Save new read pointer. BR 19$ ; Done. ; ; Mode 2. Read next block, and wait for completion of second. ; 13$: MOV #2,RDSTAT ; Set mode to next. READ$ #FDBIN,#INBUF1,#BUFLEN,,#INEFN1,#INISB1,,100$ TSTB INISB2 ; Are we waiting for this operation? BNE 130$ ; No. WTSE$S #INEFN2 ; Yes. Wait... 130$: MOV INISB2+2,RDLEN ; Get length read. MOV #INBUF2,RDPTR ; Save new read pointer. BR 19$ ; Done. ; 19$: TST RDLEN ; Anything in there? BEQ 110$ ; No. MOV (SP)+,R0 ; Yes. ; 20$: MOV RDPTR,R1 ; Get read pointer. MOV (R1),R1 ; Get next word. ADD R1,CKSUM ; Add word to checksum. INC RDPTR ; Bump pointer. INC RDPTR DEC RDLEN ; Decrement length. DEC RDLEN CLC ; Clear carry. RETURN ; 100$: TST RDSTAT ; First read? BEQ 105$ ; Yes. We shall abort. CMPB #IE.EOF,FDBIN+F.ERR ; EOF? BNE 105$ ; Nope. MOV #6,RDSTAT ; Yes. RETURN ; 105$: TST (SP)+ ; Remove return address. 110$: MOV (SP)+,R0 ; Restore R0. MOV #6,RDSTAT SEC ; Errror. RETURN ; Return. ; ; UNRDWD - Unread word. ; ; In: R1 - Word. ; UNRDWD: MOV R1,UNGETC ; Save word. MOV #-1,UNGETF ; Set flag. RETURN ; Done. ; ; ENINIT - Encode init. ; ; No registers are modified. ; ENINIT: CLR CKSUM ; Clear checksum. CLR RDLEN ; Clear length of available data. CLR UNGETF ; Clear unget flag. CLR RDSTAT ; Clear read state. RETURN ; ; CRHDR - Create header. ; ; This routine will write the prefix of the input file ; to an output file. ; CRHDR: JSR R5,PUTSTR ; Output first line. .WORD BEGSTR .WORD 0 BCS 10$ GTIM$S #ARGBLK+6 JSR R5,PUTSTR ; Output a remark. .WORD VERFMT .WORD 3 .WORD 0,REMSTR .WORD 1,VER .WORD 1,VER+2 BCS 10$ JSR R5,EXPFN ; Expand filename proper. .WORD FDBIN+F.FNB+N.FNAM ; From here. .WORD FNBUF ; To here. JSR R5,PUTSTR ; Output second line. .WORD NAMFMT .WORD 2 .WORD 0,NAMSTR .WORD 0,FNBUF BCS 10$ MOV #CODBUF,R0 ; Buffert to hold encoded data. MOV #FATT,R2 ; Buffert with original data. MOV #40/2,R3 ; # of words... 1$: MOV (R2)+,R1 ; Get word. CALL ENCWRD ; Encode word. SOB R3,1$ ; Repeat. CLRB (R0) ; Mark end of buffer. JSR R5,PUTSTR ; Output attributes. .WORD F11FMT .WORD 2 .WORD 0,F11STR .WORD 0,CODBUF BCS 10$ JSR R5,PUTSTR ; Output file protection. .WORD PROFMT .WORD 2 .WORD 0,PROSTR .WORD 1,FPROT BCS 10$ JSR R5,PUTSTR ; Output filesize. .WORD SIZFMT .WORD 2 .WORD 0,SIZSTR .WORD 0,FDBIN+F.HIBK BCS 10$ BIT #200,FCHAR ; File contigous? BEQ 5$ ; No. JSR R5,PUTSTR .WORD CNTSTR .WORD 0 BCS 10$ 5$: JSR R5,PUTSTR ; Output data. .WORD DATSTR .WORD 0 BCS 10$ 10$: RETURN ; Done. ; ; EXPFN - Expand filename. ; ; Convert filename from radix50 to nul-terminated string. ; ; In: (R5) - Address of filename as 4 r50 words. ; 2(R5) - Buffer where to place output filename. ; ; No registers are modified. ; EXPFN: MOV R0,-(SP) ; Save registers. MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV (R5)+,R3 ; Get pointer to R50 filename. MOV (R5),R0 ; Get pointer to resulting filename. MOV (R3)+,R1 CALL $C5TA ; Convert. MOV (R3)+,R1 CALL $C5TA ; Convert. MOV (R3)+,R1 CALL $C5TA ; Convert. MOVB #'.,(R0)+ ; Insert dot. MOV (R3)+,R1 CALL $C5TA ; Convert. CLRB (R0) ; Terminate string. ; MOV (R5)+,R0 ; Get destination again. MOV R0,R1 ; In both R0 and R1. 10$: CMPB (R0)+,#40 ; Space? BEQ 10$ ; Yes. Do next. DEC R0 ; No. Back up. MOVB (R0)+,(R1)+ ; Copy char. BNE 10$ ; Unless end of string, repeat. MOV (SP)+,R3 ; Restore registers. MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RTS R5 ; Done. ; ; PUTSTR - Output a formatted string on outfile. ; ; In: R5 - Argument block. ; (R5) - Address of format string. ; 2(R5) - Number of arguments. ; n(R5) - Type and address of argument. ; ; If type = 0, we use the argument itself. ; If type = 1, we use the argument as address of value to fetch. ; PUTSTR: MOV R0,-(SP) ; Save registers. MOV R1,-(SP) MOV R2,-(SP) MOV (R5)+,R1 ; Get format string address. MOV (R5)+,R2 ; Get # of arguments. BEQ 20$ ; There was none??? MOV #ARGBLK,R0 ; Point to argument block. 10$: TST (R5)+ ; Zero? BEQ 15$ ; Yes. MOV @(R5)+,(R0)+ ; No. Use address indirect. BR 16$ 15$: MOV (R5)+,(R0)+ ; Copy argument to argument block. 16$: SOB R2,10$ ; And loop. 20$: MOV #BUF,R0 ; Output buffer. MOV #ARGBLK,R2 ; Argument block. CALL $EDMSG ; Edit message. SUB #BUF,R0 ; Calculate string length. MOV R0,R1 ; Move length to R1. PUT$ #FDBOUT,#BUF,R1 ; Output string. MOV (SP)+,R2 ; Restore registers. MOV (SP)+,R1 MOV (SP)+,R0 RTS R5 ; Return. ; ; ENCWRD - Encode word ; ; In: R0 - Buffert pointer ; R1 - Word ; ; Out: R0 - Updated ; R1 - Destroyed ; ; All other registers are unmodified. ; ENCWRD: MOV R4,-(SP) ; Save register. MOV R5,-(SP) MOV R0,R5 ; Move pointer to R5. MOV #3,R4 ; Loop counter. ADD #3,R5 ; Point at end of 3-byte sequence. MOV R1,R0 ; Move word to R0. 10$: MOV #50,R1 ; Divide by 50. DIVV MOVB CODTAB(R1),-(R5) ; Save char. SOB R4,10$ ; Loop. TST R0 ; Remainder? BEQ 20$ ; No. ADD #50,R1 ; Yes. Correct value. MOVB CODTAB(R1),(R5) ; Save correct char. 20$: ADD #3,R5 ; Point at end of new string. MOV R5,R0 ; Restore pointer to R0. MOV (SP)+,R5 ; Restore registers. MOV (SP)+,R4 RETURN ; ; DECWRD - Decode word. ; ; In: R0 - Buffer pointer ; ; Out: CS - Error. Unknown character (R0) in buffer. ; CC - Ok. R0 - updated. ; R1 - decoded word. ; ; All other registers are preserved. ; DECWRD: JSR R5,$SAVRG ; Save R3-R5. MOV R0,R5 ; Move pointer to R5. MOV #3,R4 ; Loop counter. CLR R1 ; Result. 10$: MOVB (R5)+,R0 ; Get character. MOV #CODTAB,R3 ; Get pointer to code table. 20$: TSTB (R3) ; End of table? BEQ 100$ ; Yes. We fail. CMPB R0,(R3)+ ; Matching char? BNE 20$ ; No. Loop. ; ; Matching character found... ; SUB #CODTAB+1,R3 ; Get position of matching char. MOV #50,R0 ; Multiply previous result by 50. MULT ; Hey ho. ADD R3,R1 ; Add new character. SOB R4,10$ ; And repeat. ; ; Done. ; MOV R5,R0 ; Restore pointer. CLC ; Clear carry. RETURN ; Done. ; ; We failed to convert. ; 100$: DEC R5 ; Backup. MOV R5,R0 ; Restore pointer. SEC ; Set carry. RETURN ; Done. ; .PSECT DATA,D,RW ; CMLB: GCMLB$ 1,COD,,CMLUN CSIBLK: .BLKB C.SIZE ; CMASK: .WORD 0 MAXWID: .WORD 24. ; Number of words/line (approx). ; FDBOUT: FDBDF$ FDAT$A R.VAR,FD.CR FDRC$A FD.PLC FDOP$A OUTLUN,CSIBLK+C.DSDS,OUTDFN,FO.WRT FDBF$A OUTEF1 OUTDFN: NMBLK$ ,,0,SY,0 FDBIN: FDBDF$ FDRC$A FD.PLC FDOP$A INLUN,CSIBLK+C.DSDS,INDFN,FO.RD FDBF$A INEFN1 INDFN: NMBLK$ ,,0,SY,0 ; IOPLI: .WORD 0 ; Arg 1 isn't used. .WORD RATFUN ; Arg 2 points to attribute table. ; RATFUN: .BYTE -2,4 ; Read protection and characteristics (4 bytes) .WORD FPROT ; Pointer to data buffert. .BYTE -4,40 ; Read attributes. (40(8) bytes) .WORD FATT ; Pointer to data buffert. .WORD 0 ; End of table. ; IOPLO: .WORD 0 ; Arg 1 isn't used. .WORD WATFUN ; Arg 2 points to attribute table. ; WATFUN: .BYTE 5,12 ; Write filename. (12(8) bytes) .WORD FDBOUT+F.FNB+N.FNAM ; Pointer to filename. WATBLK: .BLKW MAXWAT*2 ; WATPTR: .WORD 0 WATCNT: .WORD 0 ; FPROT: .WORD 0 FCHAR: .WORD 0 FATT: .BLKB 40 FILSIZ: .WORD 0 ; INISB1: .BLKW 2 INISB2: .BLKW 2 OUTSB1: .BLKW 2 OUTSB2: .BLKW 2 ; STRPTR: .WORD 0 STRLEN: .WORD 0 ; RDLEN: .WORD 0 RDPTR: .WORD 0 RDSTAT: .WORD 0 WRSTAT: .WORD 0 WRFLG: .WORD 0 ; UNGETC: .WORD 0 UNGETF: .WORD 0 ; RPTCNT: .WORD 0 RPTWD: .WORD 0 ; VER: .BLKW 2 ARGBLK: .BLKW 32. CKSUM: .WORD 0 SAVSP: .WORD 0 ; BUF: .BLKB 200. FNBUF: .BLKB 14. CODBUF: .BLKB 80. ; INBUF1: .BLKB BUFLEN INBUF2: .BLKB BUFLEN OUTBF1: .BLKB BUFLEN OUTBF2: .BLKB BUFLEN ; .PSECT TABLE,D,RO ; P1TAB: .WORD BEGSTR,0 .WORD 0 ; P2TAB: .WORD NAMSTR,SETNAM .WORD REMSTR,DOREM .WORD F11STR,SETATT .WORD SIZSTR,SETSIZ .WORD PROSTR,SETPRO .WORD CNTSTR,SETCNT .WORD DATSTR,DODAT .WORD 0 ; P3TAB: .WORD ENDSTR,0 .WORD 0 ; .PSECT TEXT,D,RO ; BEGSTR: .ASCIZ /(BEGIN)/ REMSTR: .ASCIZ /(REMARK / NAMSTR: .ASCIZ /(FILE / F11STR: .ASCIZ /(F11A / SIZSTR: .ASCIZ /(SIZE / PROSTR: .ASCIZ /(PROTECTION / CNTSTR: .ASCIZ /(CONTIGOUS)/ DATSTR: .ASCIZ /(DATA)/ ENDSTR: .ASCIZ /(END / ; CODTAB: .ASCIZ /+ABCDEFGHIJKLMNOPQRSTUVWXYZ?.:0123456789-/ ; V2FMT: .ASCIZ /COD %R%R (c) 1996 by Johnny Billquist/ VERFMT: .ASCIZ /%I Created by COD %R%R %Y %2Z)/ NAMFMT: .ASCIZ /%I%I)/ F11FMT: .ASCIZ /%I%I)/ SIZFMT: .ASCIZ /%I%T)/ PROFMT: .ASCIZ /%I%P)/ ENDFMT: .ASCIZ /%I%P)/ DATFMT: .ASCIZ /<%I>/ ; BF: .ASCII /Unrecognized line: / BFLEN=.-BF IL: .ASCII /Illegal line: / ILLEN=.-IL CKERR: .ASCII /Checksum error./ CKELEN=.-CKERR PETXT: .ASCII /Parse error - / PELEN=.-PETXT POETXT: .ASCII /Error parsing output./ POELEN=.-POETXT PIETXT: .ASCII /Error parsing input./ PIELEN=.-PIETXT MOETXT: .ASCII /Too many output files specified./ MOELEN=.-MOETXT MIETXT: .ASCII /Too many input files specified./ MIELEN=.-MIETXT ; IOERR: .ASCIZ /Error opening %I for input./ INOHD: .ASCII /No (BEGIN) found in file./ INHLEN=.-INOHD IBADHD: .ASCII /No (DATA) found in file./ IBHLEN=.-IBADHD OOERR: .ASCIZ /Error opening %I for output./ OWERR: .ASCII /Error writing to output file./ OWELEN=.-OWERR DELERR: .ASCII /Error deleting output file./ DELEN=.-DELERR ; ATTERR: .ASCII /Too many attributes./ ATTLEN=.-ATTERR BADEND: .ASCII /No end-marker ")" when expected in line./ BELEN=.-BADEND CORDAT: .ASCII /Corrupted data, aborting. Line was:/ CDLEN=.-CORDAT WNERR: .ASCII /Width must be atleast 8 characters./ WNELEN=.-WNERR ; HLPMSG: .ASCII /HE - This help/<15><12> .ASCII /ID - Identify program/<15><12> .ASCII /WI:n - Maximum line width n/<15><12> .ASCII /NM - No messages/<15><12> .ASCII /EN - Encode/<15><12> .ASCII /DE - Decode (Default)/ HLPLEN=.-HLPMSG ; .END START