*=============================== -*- Mode: Merlin -*- * Executioner (EXEC file maker) * Glen E. Bredon Dec 24, 86 *------------------------------- DATE TR ADR TR EXP OFF SAVOBJ KBD * Data LINSTART = #"." ;This is the character at start of ;each line, but not checked for. ;This is simply to avoid the possibility ;of a DOS command at the beginning of a line. * Usage by this program: FPNT = $D0 ;Pointer to catalog entry LEN = $D2 ;For reading directory ENTPER = LEN+1 ; " THISCNT = $D4 ; " NL = $D5 ;PRDEC usage NH = $D6 ; " NFL = $D7 ; " BASFLAG = $D8 ;Flags basic program MAXLEN = $D9 ;Count for len of basic prog PFLAG = $DB ;Flags extra 6-bit packing ADD0 = $DC ;Used to compute expansion ADD1 = $DD ; factor at end ADD2 = $DE PNT = $E0 ;Pointer to code TEMP = $E2 ;For 6-bit unpacker only FLAG = $E3 ;Misc use ADRS = $E2 ;For line header TXTP = $E4 ;For SENDMSG CNT = $E6 ;Count up for len of code SLASHFLG = $E8 ;Disable slash on file name BUFPNT = $E9 ;Pointer into 1 pg wrt buf YSAV = $EA COUNT = $EB ;& C,D: size of EXEC file LINLEN = $EE ;# of bytes on each line PACKFLG = $EF ;+ if ord, V set if 6-bit THREE = $F0 ;Count (-) for three bytes XSAV = $F1 BYT0 = $F2 ;Temp storage when packing BYT1 = $F3 BYT2 = $F4 BYT3 = $F5 STARTFLG = $F6 ;Flags initial entry SIZ0 = $F7 ;Used to compute exp factor SIZ1 = $F8 CHKSUM = $FF ;Used only in packing modes LOADADR = $1000 ;Start adrs written to file FILEBUF = $1000 ;Buffer for our file write WBUF = $1800 ;1 page buffer for writing CATBUF = $1C00 ;1 block needed for this PROGBUF = $3000 ;Source file load adrs FILES = $8000 ;Catalog entry list * Apple stuff: CH = $24 CV = $25 IN = $200 DOSWARM = $3D0 RESET = $3F2 MLI = $BF00 DEVNUM = $BF30 BITMAP = $BF58 ALTCHRS = $C00F SPEAKER = $C030 TOKENS = $D0D0 ;Applesoft token table TABV = $FB5B CLREOP = $FC42 HOME = $FC58 WAIT = $FCA8 RDKEY = $FD0C GETLNZ = $FD67 CROUT = $FD8E PRBYTE = $FDDA COUT = $FDED MONITOR = $FF69 * MLI call codes: quit = $65 create = $C0 destroy = $C1 setinfo = $C3 getinfo = $C4 online = $C5 setpfx = $C6 getpfx = $C7 open = $C8 read = $CA write = $CB close = $CC seteof = $D0 geteof = $D1 *=============================== STADR MAC LDA #]1 STA ]2 LDA #>]1 STA ]2+1 <<< INCD MAC INC ]1 BNE NI INC ]1+1 NI <<< MOVD MAC LDA ]1 STA ]2 LDA ]1+1 STA ]2+1 <<< DOS MAC JSR MLI DFB ]1 DA ]2 <<< WRITE MAC LDX ]1 LDY #0 LUP INY LDA ]1,Y JSR WRTBYTE DEX BNE LUP <<< *=============================== TYP $FF ;Make SYS file ORG $2000 JMP START0 HEX EEEE ;STARTUP signature DFB $40 ;Its max length STARTUP DS $40 ;Prefix (etc) for dest file *------------------------------------ * File type names (followed by type). * Change the "NON" ones to add types. *------------------------------------ TYPES ASC "BAD"01 ASC "TXT"04 ASC "BIN"06 ASC "DIR"0F ASC "ADB"19 ASC "AWP"1A ASC "ASP"1B ASC "S16"B3 ASC "NDA"B8 ASC "CDA"B9 ASC "TOL"BA ASC "DOC"BF ASC "PNT"C0 ASC "PIC"C1 ASC "FON"C8 ASC "CMD"F0 ASC "LNK"F8 ASC "BAS"FC ASC "VAR"FD ASC "REL"FE ASC "SYS"FF LUP 11 ASC "NON"00 --^ TYPEND ERR *-TYPES/$84 START0 LSR STARTFLG ;Signal initial entry START STADR EXIT ;RESET ;Set up RESET vector EOR #$A5 STA RESET+2 LDX #$17 LDA #1 ]LUP STA BITMAP,X ;Min bit map (we will do LDA #0 ; the worrying). DEX BPL ]LUP TXS LDX #$11 ;Blank filename in case ]LUP STA FILENAME-1,X ;of multiple use DEX BNE ]LUP STA PFLAG ;Init extra packing flag STA BUFPNT ; and buffer ptr STA COUNT+1 STA COUNT+2 STA PACKFLG ; and packing flag off STA THREE ; and set 0 mod 3 LDA #%11001111 STA BITMAP LDA #"U"&$9F ;Turn on 40 columns JSR COUT JSR HOME STA ALTCHRS ;Enable mousetext JSR WIRE ;Print barbed wire JSR CROUT LDX #14 JSR SENDEXEC ;Print EXEC LDX #2 BIT STARTFLG BMI :LUP LDX #20 :LUP TXA JSR TABV LDA #19 STA CH JSR SENDUT ;Print UTIVE on this line LDY #40 ; & wipe from next :WIP LDA #" " JSR COUT DEY BNE :WIP TYA JSR WAIT DEX CPX #2 BGE :LUP ;Branch till it is on top LDA #3 STA CNT LDA #2 JSR TABV BIT STARTFLG BMI :OVER ;Skip if not initial entry :CLOOP LDX #14 :CLACK JSR CLACK ;Move words out DEX CPX #4 BGE :CLACK ;Till this point :BACK INX JSR CLACK ;Move them back together CPX #14 BLT :BACK LDX #$30 :CLICK BIT SPEAKER ;Make a noise LDY #$C0 :PAUSE INY BNE :PAUSE DEX BNE :CLICK DEC CNT BNE :CLOOP ;Repeat twice more :OVER LDA #7 STA CH JSR SENDMSG ASC "By Glen"00 LDA #27 STA CH JSR SENDMSG ASC "Bredon"8d8d ASC "Produces an EXEC text file from any" HEX 8D ASC "ProDOS file."8d8d ASC "Packed format?"00 JSR YORN STA STARTFLG ROR PACKFLG ;- if packing wanted BPL :STD ;Skip if no packing LDA #6 JSR TABV JSR SENDMSG HEX 8D ASC "4 bit (HEX) or 6 bit packing? (4/6):" BRK :KY JSR RDKEY CMP #"6" BEQ :RR CMP #"4" BNE :KY CLC :RR JSR PUSHOUT BCC :STD LDA #%11000000 ;Signal 6-bit packing mode STA PACKFLG ; by V flag :STD JSR SENDMSG HEX 8D8D ASC "Prefix: "00 DOS getpfx ;PFXPARMS BCS :BMLIERR LDX IN+$40 BEQ :INPUT ;Branch if no pfx :PPF INY LDA IN+$40,Y STA IN-1,Y ORA #$80 JSR COUT ;Show prefix DEX BNE :PPF LDX IN+$40 :INPUT JSR INPUT0 ;Get new pfx BEQ :JEX ;Abort if pfx erased STX IN+$40 :MOVP LDA IN-1,X STA IN+$40,X DEX BNE :MOVP DOS setpfx ;PFXPARMS :BMLIERR BCS :DMLIERR JSR CAT ;Read the catalog JSR SENDMSG ; according to prefix HEX 8D8D ASC "File to convert: "00 LDX #-1 STX SLASHFLG ;Disallow slash and input INX ; at most 15 chars JSR PRFILE ;Start with last cat entry, JSR INPUT ; note this zeros COUNT BNE :ON :JEX JMP EXIT ;Abort if name erased :ON STX IN+$80 STX FILENAME :MOV LDA IN-1,X STA IN+$80,X ;Set name for getinfo etc STA FILENAME,X ;Save inside EXEC file DEX BNE :MOV DOS getinfo ;INFPARMS :DMLIERR BCS :MLIERR LDA #$4A ;Incompat format error LDX INFTYPE CPX #$F BEQ :MLIERR ;Error if a directory STADR IN+$80 ;OPATH JSR OPEN ;Open the source file DOS geteof ;EOFPARMS BCS :MLIERR ; and get its length LDX #PARMEND-PARMS-1 :MVP LDA INFPARMS,X STA PARMS,X ;Save its info in EXEC DEX ; file for setinfo call CPX #ACC-PARMS BGE :MVP LDA EOF+2 STA ZERO ;Zero out the three STA ZERO+1 ; unused info bytes STA ZERO+2 BNE :TOOBIG ;Carry is clear LDA EOF STA SIZ0 STA RWCNT STA PNT LDA EOF+1 STA SIZ1 STA RWCNT+1 ADC #>PROGBUF STA PNT+1 LDA #$8200 CMP EOF LDA #>$8200 SBC EOF+1 :TOOBIG BLT TOOBIG JSR SHOWSPEC ;Show file info and BLT :START ; restart if not ok STADR PROGBUF ;RWBUF DOS read ;RWPARMS ;Load the file BCS :MLIERR DOS close ;CLSPARMS :MLIERR BCS MLIERR LDA #$61 ;Mark end of file for LDY #0 ; packing routines STA (PNT),Y JSR CNTPACK JSR GETDEST ;Ask for dest filename BEQ EXIT STX IN+$C0 :MOVD LDA IN-1,X STA IN+$C0,X DEX BNE :MOVD JSR MAKEFILE ;Write the EXEC file BCC EXIT :START JMP START EXIT DOS close ;CLSPARMS DOS quit ;QPARMS BRK *============================= * MLI error handling and quit: *----------------------------- TOOBIG LDA #$FF ;Fake err code MLIERR PHA PHA DOS close ;CLSPARMS JSR SENDMSG HEX 8D8D ASC "MLI error: $"00 PLA JSR PRBYTE ;Print error code JSR CROUT PLA LDX #ERREND-ERRORS :CERR DEX BMI HIT ;Skip if err code not in tbl CMP ERRORS,X BNE :CERR LDY ERROFF,X :PERR LDA ERRORS,Y BEQ HIT JSR COUT ;Print error message INY BNE :PERR HIT JSR SENDMSG HEX 8D8D ASC "Hit a key"8d00 JSR RDKEY JSTART JMP START *=============================== * Routine to create dest file, * and call file converter. *------------------------------- MAKEFILE STADR IN+$C0 ;OPATH DOS create ;CREPARMS BCC :OK ;Skip if file created ok CMP #$47 ;Duplicate file BNE MLIERR ;Error if not JSR SENDMSG HEX 8D8D ASC "File exists, delete it?"00 JSR YORN BCC JSTART ;Restart if N DOS destroy ;DESPARMS BCC MAKEFILE ;Else create it :MLIERR JMP MLIERR ;Error if locked, etc :OK JSR OPEN ;Open destination file JSR WRTFILE ;Write data to it and close DOS close ;CLSPARMS BCS :MLIERR TAX ;=0 LDY #3 :DOUB LDA COUNT,X ;Double size ROL STA BYT0,X ; and save it STA ADD0,X INX DEY BNE :DOUB DEX ;=2 :MUL ASL ADD0 ;Multiply ADD by 4 ROL ADD1 ; = size x 8 ROL ADD2 INY DEX BNE :MUL :ADD LDA ADD0,X ;Add size x 8 to ADC BYT0,X ; size x 2 to get STA BYT0,X ; size x 10 INX DEY BPL :ADD LDA SIZ1 ;Add (orig size)/2 LSR ; to size x 10 for TAX ; rounding final factor LDA SIZ0 ROR ADC BYT0 STA BYT0 TXA ADC BYT1 STA BYT1 BCC :PER INC BYT2 :PER LDA BYT0 ;Divide this by orig size SBC SIZ0 ; (don't bother setting STA BYT0 ; carry at entry - this is LDA BYT1 ; only an approx anyway. SBC SIZ1 ;Division done by repeated STA BYT1 ; subtraction (quotient LDA BYT2 ; cannot be more than SBC #0 ; about 40). STA BYT2 INY ;Count quotient in Y BGE :PER TYA PHA ;Exp factor x10 JSR HOME JSR SENDMSG HEX 8D8D8D8D00 JSR WIRE ;Start a wire box JSR DWNARROW ;line 2 ASC 'K' ASC " EXEC file length = $"00 LDA COUNT+2 BEQ :SKP JSR PRBYTE :SKP LDA COUNT+1 JSR PRBYTE ;Print length LDA COUNT JSR PRBYTE JSR UPARROW JSR DWNARROW ASC 'K' ASC " Expansion factor = "00 PLA :LX0 LDX #0 :C10 CMP #10 ;Divide exp factor by 10 BLT :DIVD SBC #10 INX ; quotient in X CPX #10 BLT :C10 INY BGE :LX0 :DIVD PHA ;Save remainder TYA BEQ :LESS ORA #"0" JSR COUT :LESS TXA ORA #"0" JSR COUT ;Print integer part LDA #"." JSR COUT PLA ORA #"0" JSR COUT ; and tenths JSR UPARROW BIT BASFLAG BPL :NOBAS ;Skip if not basic JSR DWNARROW ASC 'K' ASC " Longest line length = "00 STY BASFLAG ;Fix so WRTDEC uses COUT LDA MAXLEN+1 LDX MAXLEN JSR WRTDEC ;Print max line length JSR UPARROW :NOBAS JSR DWNARROW ASC 'K' ASC " Another?"00 JSR UPARROW JSR DWNARROW ASC 'K'00 JSR UPARROW JSR WIRE LDA CV SEC SBC #4 JSR TABV ;Position cursor for YORN LDA #10 STA CH JMP YORN ;Exit through YORN WIRE JSR :DIAM ;Print diamond LDX #19 :TOP JSR SENDMSG ;Print barbed wire ASC 'UH'00 DEX BNE :TOP ; then another diamond :DIAM LDA #'[' JMP COUT DWNARROW JSR SENDMSG ;Print down arrows at ASC 'J'00 LDA #39 ; both ends of line STA CH LDA #'J' JSR COUT JMP SENDMSG ;Fall into SENDMSG UPARROW LDA #39 ;Print up arrow at right STA CH ; side of screen LDA #'K' JMP COUT OPEN DOS open ;OPARMS BCS :MLIERR LDA OREF STA EOFREF STA RWREF RTS :MLIERR JMP MLIERR TIMER LDA #'C' ;Hourglass STA $502 STA $525 RTS *============================================ * Routines that actually write the EXEC file. *-------------------------------------------- WRTFILE STADR $100 ;RWCNT ;Set to write one page buf STADR WBUF ;RWBUF LDA INFTYPE CMP #$FC ;BAS file type BNE :NOTBAS JSR SENDMSG HEX 8D8D ASC "Original is a BASIC program, do you"8D ASC "want a listing type EXEC file?"00 JSR YORN BCC :NOTBAS ROR BASFLAG JMP MAKBAS ;Go with Y=0 :NOTBAS JSR TIMER WRITE CALL ;Write CALL-151 LDY #0 STY CHKSUM STY ADRS LDA #>$E00 STA ADRS+1 ;Write setinfo header :HEAD JSR WRTADR0 ;Write line header LDX #$18 ;Count for $18 bytes :HLUP LDA SETINF,Y JSR WRTHEX2 ;Write one hex byte DEX BEQ :LIN LDA SETINF,Y BNE :CONT CPY #FILENAME-SETINF BGE HEAD2 :CONT JSR WRTSPC ;Space after byte INY BNE :HLUP ;Always :LIN LDA SETINF,Y BNE :ON CPY #FILENAME-SETINF BGE HEAD2 :ON LDA ADRS ;Next line CLC ADC #$18 STA ADRS INY BNE :HEAD ;Always (less that 1 page) HEAD2 BIT PACKFLG BPL :HDONE ;Skip if no packing LDY #0 STY ADRS LDA #>$F00 STA ADRS+1 ;Write unpacker header STADR READSQZ ;PNT BVC :HEAD ;Branch if 4-bit mode STADR RS6 ;PNT BIT PFLAG BPL :HEAD ;Branch for standard 6-bit STADR RS6P ;PNT :HEAD JSR WRTADR0 ;Write line header LDX #$18 ;Count for $18 bytes :HLUP LDA (PNT),Y BNE :WRIT INY LDA (PNT),Y ;Check for 2-0s end mark BEQ :F00G DEY LDA (PNT),Y :WRIT JSR WRTHEX2 ;Write one hex byte INY INY LDA (PNT),Y DEY DEX BEQ :LIN ORA (PNT),Y BEQ :F00G JSR WRTSPC ;Space after byte JMP :HLUP :LIN ORA (PNT),Y ;Check end mark BEQ :F00G LDA ADRS ;Next line CLC ADC #$18 STA ADRS BCC :HEAD ;Always :F00G JSR WRTCR WRITE F00G :HDONE STADR LOADADR ;ADRS ;Set to write code STADR PROGBUF ;PNT ;Actual code adrs LDA #$18 STA LINLEN ;24 bytes for ord dump LDA EOF EOR #$FF STA CNT ;Calculate for count up LDA EOF+1 EOR #$FF STA CNT+1 INCD CNT BEQ :DONE ;Safety if no file :LINLUP BIT PACKFLG BPL :WAD LDA #$20 ;32 bytes/line if pack-4 BVC :SL LDA #$30 ;48 if pack-6 :SL STA LINLEN JSR WRTCR BIT PACKFLG BVC :NOADR LDA #LINSTART JSR WRTBYTE ;Avoid DOS commands JMP :NOADR :WAD JSR WRTADR ;Write line header :NOADR LDX LINLEN ;Count for $18/20/30 bytes :LUP LDY #0 LDA (PNT),Y EOR CHKSUM STA CHKSUM LDA (PNT),Y CMP #$61 BEQ :WH ;Skip pack if endmark chr BIT PACKFLG BVC :WH ; or 4-bit or std mode BIT THREE BMI :WH ; or 4 byte packet undone BIT PFLAG BPL :WH ; or std 6-bit mode. :IY INY BMI :DOIT CMP (PNT),Y ;Check for repetitions BEQ :IY :DOIT DEY ;Max $7F TYA CMP #3 BLT :WH ;Skip if < 4 reps JSR PACKBYTS ;Make packed packet BCS :DONE BCC :DX :WH LDY #0 LDA (PNT),Y JSR WRTHEX ;Write one byte INCD CNT BEQ :DONE ;Exit when code done INCD ADRS ;Bump fake adrs INCD PNT ; and actual adrs :DX DEX BEQ :LINLUP ;Branch if new line BIT PACKFLG BMI :LUP JSR WRTSPC ;Else write space JMP :LUP :DONE BIT PACKFLG BPL :NOCHK LDA CHKSUM ;Write checksum if packed JSR WRTHEX :NOCHK JSR WRTCR BIT PACKFLG BPL :FIN JSR WRTCR ;Empty line if packed :FIN WRITE BSAVE ;Write BSAVE WRITE IN+$80 ; and filename WRITE AD ; and A parameter, etc LDA EOF+1 JSR WRTHEX2 ;Write L parameter LDA EOF JSR WRTHEX2 JSR WRTCR ;CR BIT PACKFLG BPL :C3 WRITE CALL2 ;Write E00G if packed JMP FINISH :C3 WRITE CALL3 ;Write E05G if not packed FINISH JSR WRTCR LDA BUFPNT ;If buffer done, skip BEQ :RET ; else write it JSR WRTBUF LDX #2 :CL LDA COUNT,X ; and set correct length STA EOF,X DEX BPL :CL DOS seteof ;EOFPARMS BCS ERR :RET RTS WRTADR0 JSR WRTCR LDA ADRS+1 JSR WRTNIB JMP WA2 WRTADR JSR WRTCR ;Write line header LDA ADRS+1 JSR WRTHEX2 WA2 LDA ADRS JSR WRTHEX2 LDA #":" BNE WRTBYTE WRTHEX BIT PACKFLG BVC WRTHEX2 ;Branch if not pack-6 STX XSAV PHA LDX THREE ;Take abs val of count TXA EOR #-1 TAX INX ; use as index to temp bytes PLA ASL ;Shift off top two bits & PHP ; put into BYT0 ASL ROR BYT0 PLP ROR BYT0 STA BYT1,X ;Store byte*4 in BYT1,2,3 CPX #2 BEQ :OFF LDX XSAV ;Exit if have not processed DEC THREE ; all three bytes RTS :OFF LDX #6 ;Reverse the order of the LDA #0 ; six bits in BYT0 :SHFT ASL BYT0 ROR DEX BNE :SHFT STA BYT0 ;They are now in high-low STX THREE ; order with 1st one at :SEND LDA BYT0,X ; top LSR LSR CLC ADC #$3F JSR WRTBYTE ;Write to file. INX CPX #4 BLT :SEND ;Send all 4 bytes LDX XSAV RTS ERR JMP MLIERR WRTHEX2 PHA ;Write hex byte LSR LSR ~ LSR LSR JSR WRTNIB PLA AND #$F WRTNIB ORA #"0" CMP #"9"+1 BLT WRTBYTE ADC #6 HEX 2C WRTCR LDA #$8D BIT PACKFLG ;If not 6-bit packed BVC WRTBYTE ; then write CR BIT THREE ;Same if #=0 mod 3 BPL WRTBYTE LDA #0 ;Else write 0s until it is JSR WRTHEX JMP WRTCR ;Loop while # not 0 mod 3 WRTSPC LDA #" " WRTBYTE AND #$7F ;Write (pos) ascii byte STY YSAV LDY BUFPNT STA WBUF,Y ;Wait for 1 page before LDY YSAV ; sending to MLI INC COUNT ;Count EXEC file size BNE :IB INC COUNT+1 BNE :IB INC COUNT+2 :IB INC BUFPNT ;Fall into WRTBUF if BNE RTN ; buffer full WRTBUF DOS write ;RWPARMS BCS ERR RTN RTS PACKBYTS LDA #"0" JSR WRTBYTE ;Write special signature LDA (PNT),Y AND #%11 CLC ADC #$3F JSR WRTBYTE ;Low two bits LDA (PNT),Y EOR CHKSUM STA CHKSUM ;Correct checksum LDA (PNT),Y LSR LSR CLC ADC #$3F JSR WRTBYTE ;Upper six bits DEY TYA LSR ;Max $7E/2 = $3F CLC ADC #$3F JSR WRTBYTE ;Length of segment/2-1 INY INY TYA LSR ;Always even ASL ;Clears carry TAY ;Length of segment ADC CNT ;Bump pointers STA CNT BCC :ON INC CNT+1 BEQ :RET ;Carry set this exit CLC :ON TYA ADC PNT STA PNT BCC :DX INC PNT+1 CLC ;Signal more to do :DX DEX DEX :RET RTS *=============================== * Routine to count repetitions * to decide packing mode *------------------------------- CNTPACK BIT PACKFLG ;Ignore if not in 6-bit mode BVC :RET LDX #0 STX FPNT LDA #>PROGBUF STA FPNT+1 :NXCNT LDY #0 LDA (FPNT),Y ;Get a byte :LUP INY BMI :SETFLG ;Pack if 128 byte segment CMP #$61 ;Ignore end mark char BEQ :SY CMP (FPNT),Y BEQ :LUP ;Loop if same as last :SY STY YSAV ;= length of segment CPY #8 ;Ignore if short BLT :OV :TYX DEY ;Transfer Y to running BEQ :OV ; counter in X INX BPL :TYX ;If total>127 then pack :SETFLG SEC ;Signal extra packing mode ROR PFLAG :RET RTS :OV LDA YSAV ;Bump pointer past segment CLC ADC FPNT STA FPNT BCC :DONE INC FPNT+1 :DONE CMP PNT LDA FPNT+1 SBC PNT+1 BLT :NXCNT ;Loop till prog done RTS *============================ * Routine to write BASIC file *---------------------------- MAKBAS JSR TIMER LDY #0 STY PACKFLG ;Defeat packing request STY LEN STY LEN+1 STY MAXLEN STY MAXLEN+1 STY PNT LDA #>PROGBUF STA PNT+1 ;Point to file WRITE NEW ;Send "NEW" JSR WRTCR :BASLUP LDA LEN ;Set max if line length CMP MAXLEN LDA LEN+1 SBC MAXLEN+1 BLT :SHORT MOVD LEN ;MAXLEN :SHORT LDY #0 STY LEN ;Restart line len count STY LEN+1 INY LDA (PNT),Y ;Link hi BEQ :DONE ;Done if link hi is zero INY LDA (PNT),Y ;Line # low TAX INY LDA (PNT),Y ; " hi JSR WRTDEC ;Send line number LDA PNT ;Point to 1st char of line CLC ADC #4 STA PNT BCC :LINLUP INC PNT+1 :LINLUP LDY #0 LDA (PNT),Y BEQ :ENDLIN ;Branch on end of line BMI :ISTOK ;Branch on token :WRT JSR WRTBAS ;Write non-token :NXT INCD PNT ;Point to next char BNE :LINLUP ;Branch always :ISTOK CMP #186 ;PRINT token? BNE :TOK LDA #'?' ;Substitute "?" BNE :WRT :TOK TAX ;Tok in X for table lookup STADR TOKENS-1 ;FPNT :DX DEX BPL :GOTTOK ;Pointing to word in table :LOOK INCD FPNT ; when X goes positive LDA (FPNT),Y BEQ :ERR ;Should not happen EOR TOKENS ;Support for Laser-128 BPL :LOOK ;Branch if word not done BMI :DX ;Count the word :GOTTOK INCD FPNT ;Point to next word LDA (FPNT),Y PHA JSR WRTBAS ;Send it PLA EOR TOKENS ;Support for Laser-128 BPL :GOTTOK ;Loop till word sent BMI :NXT ;Then back to program :ERR LDA #0 ;Illegal token, abort JMP MLIERR :ENDLIN JSR WRTCR ;End line with CR INCD PNT JMP :BASLUP ;Next line :DONE WRITE SAVE ;Send "SAVE " WRITE IN+$80 ; and filename JMP FINISH ; and go wind it up. *====================================== * Line number printer for BASIC listing *-------------------------------------- WRTDEC STA NH ;Save # STX NL LDX #9 ;Loop count STX NFL ; and table index :LOAD0 LDY #"0" :DIV LDA NL CMP :NUMTBL-1,X LDA NH SBC :NUMTBL,X ;Compare w power of 10 BCC :DIVD ;If less then have quot. STA NH LDA NL ;Else subtract that power SBC :NUMTBL-1,X STA NL INY ; count quotient BNE :DIV ; and branch always :DIVD TYA ;Y has quotient in ascii DEX BEQ :PRD ;Always write final digit CMP #"0" BEQ :PDIG STA NFL ;Flag a nonzero digit :PDIG BIT NFL BPL :NXDIG ;Skip leading zeros :PRD JSR WRTBAS0 :NXDIG DEX BPL :LOAD0 RTS :NUMTBL DA 1,10,100,1000,10000 WRTBAS0 BIT BASFLAG ;If BASFLAG is + BMI WRTBAS JMP COUT ; then print to screen WRTBAS INCD LEN ; else count the byte JMP WRTBYTE ; and write to file *=============================== * Routine to show specifications * of file to be converted. *------------------------------- SHOWSPEC LDA #10 JSR TABV JSR CLREOP JSR SENDMSG HEX 8D ASC "File name: "00 LDX IN+$80 :PN INY LDA IN+$80,Y JSR COUT DEX BNE :PN JSR SENDMSG HEX 8D ASC "File type: "00 LDA INFTYPE LDY #TYPEND-TYPES-1 ]LUP CMP TYPES,Y ;Check name list BNE :NO LDX #3 :PT LDA TYPES-3,Y JSR COUT INY DEX BNE :PT BEQ :SKP ;Skip hex routine :NO DEY DEY DEY DEY BPL ]LUP ;Loop till through list :USEH PHA ;Not found save type LDA #"$" JSR COUT PLA JSR PRBYTE ;Print file type :SKP JSR SENDMSG HEX 8D ASC "Aux type: $"00 LDA INFAUX+1 JSR PRBYTE LDA INFAUX JSR PRBYTE JSR SENDMSG HEX 8D ASC "File size: $"00 LDA EOF+1 JSR PRBYTE LDA EOF JSR PRBYTE JSR SENDMSG HEX 8D8D ASC "Ok?"00 YORN JSR SENDMSG ASC " (Y/N):"00 ]LUP JSR RDKEY CMP #"["&$9F BEQ QUIT AND #%11011111 CMP #"Y" BEQ PUSHOUT EOR #"N" BNE ]LUP LDA #"N" PUSHOUT PHP JSR COUT PLP RTS ;Returns with CS if Y QUIT JMP EXIT *============================= * Input routine, headed by get * destination EXEC file name. *----------------------------- GETDEST LDA #15 JSR TABV JSR CLREOP JSR SENDMSG HEX 8D ASC "Name of EXEC file to create:"8d00 LDX STARTUP BEQ INPUT0 ;Skip if no startup :LUP INY LDA STARTUP,Y ;Print the startup ORA #$80 CMP #"A" BLT :NU AND #%11011111 :NU STA IN-1,Y ;And save it as if typed JSR COUT DEX BNE :LUP LDX STARTUP INPUT0 LSR SLASHFLG INPUT TXA TAY LDA #" " :FAKE STA IN,Y ;Defeat illegal picks INY CPY #$40 BLT :FAKE :KEY JSR RDKEY CMP #"U"&$9F ;But support after backspc BNE :NOU LDA IN,X ;Pick from previous input ORA #$80 :NOU CMP #"." BEQ :OK CMP #$FF BEQ :BS CMP #$88 BEQ :BS BIT SLASHFLG BPL :SLS ;Skip if not orig filename LDY IN+$40 BEQ :SLS ; or no prefix CMP #"K"&$9F BEQ :DP CMP #"J"&$9F BNE :NOSL JSR INCPNT ;Next cat entry LDY #0 LDA (FPNT),Y ;Ignore if no more BNE :PRFILE :DP JSR DECPNT ;Previous cat entry :PRFILE JSR ERASE ;Erase current name JSR PRFILE ;Print next one JMP :KEY :SLS CMP #"/" BEQ :OK :NOSL CMP #$8D BEQ :DONE CMP #"["&$9F ;ESC at any input returns BEQ :ABORT ; to program start. CMP #"0" BLT :KEY CMP #"9"+1 BLT :OK CMP #"A" BLT :KEY AND #%11011111 CMP #"Z"+1 BGE :JKEY :OK STA IN,X JSR COUT INX CPX #$10 BLT :JKEY BIT SLASHFLG ;Length of source file BMI :BS ; at most 15 CPX #$40 ;Other input to 63 BLT :JKEY :BS TXA BEQ :JKEY DEX JSR BACKSPC :JKEY JMP :KEY :DONE TXA RTS :ABORT JMP START BACKSPC JSR :BS ;Backspace LDA #" " JSR COUT ;Wipe previous char :BS LDA #$88 JMP COUT ; & backspace again PRFILE LDY #0 LDA (FPNT),Y STA COUNT ;Name length BEQ :ZERO ;Ignore if no name :NY INY LDA (FPNT),Y ORA #$80 STA IN,X ;Save as if from keybd JSR COUT INX DEC COUNT BNE :NY :ZERO LDA #0 STA IN,X ;Mark for pick RTS ERASE TXA ;X holds cursor pos BEQ :RET :BS JSR BACKSPC DEX BNE :BS :RET RTS SENDEXEC STX CH JSR SENDMSG ASC " EXEC"00 RTS SENDUT JSR SENDMSG ASC "UTIONER "00 RTS CLACK JSR SENDEXEC ;Print "EXEC" TXA EOR #$FF ;Calculate # of middle CLC ; spaces ADC #15 ASL TAY BEQ :NOS :SPC LDA #" " JSR COUT ; and print them DEY BNE :SPC :NOS JSR SENDUT ; then print "UTIONER" LDA #$40 JMP WAIT ;Let him see it *=========================== * Strings put into EXEC file *--------------------------- CALL STR "CALL-151" CALL2 STR "E00G" CALL3 STR "E05G" AD STR ",A$1000,L$" ERR LOADADR-$1000 F00G STR "F00G" BSAVE STR "BSAVE " SAVE STR "SAVE " NEW STR "NEW" *=============================== * Parameter tables for this pgm. *------------------------------- CLSPARMS DFB 1 DFB 0 QPARMS DFB 4 DFB 0 DA 0 DFB 0 DA 0 INFPARMS DFB 10 DA IN+$80 DFB 0 INFTYPE DFB 0 INFAUX DA 0 DFB 0 DA 0 DA 0,0 DA 0,0 OPARMS DFB 3 OPATH DA IN+$80 DA FILEBUF ;File buffer OREF DFB 0 EOFPARMS DFB 2 EOFREF DFB 0 EOF DFB 0,0,0 RWPARMS DFB 4 RWREF DFB 0 RWBUF DA PROGBUF ;File load adrs RWCNT DA 0 DA 0 CREPARMS DFB 7 DA IN+$C0 DFB $C3 DFB 4 ;Text DA 0 DFB 1 DA 0,0 DESPARMS DFB 1 DA IN+$C0 PFXPARMS DFB 1 DA IN+$40 VAR TXTP ;COUT PUT /HARD1/MERLIN/LIB/SENDMSG *================== * Catalog routines: *------------------ GOERR JMP MLIERR CAT LDA #0 STA RWCNT STA RWBUF LDA #2 ;Read 1 block STA RWCNT+1 LDA #>CATBUF STA RWBUF+1 STADR IN+$40 ;OPATH JSR OPEN ;Open dir of the pfx DOS read ;RWPARMS BCS GOERR MOVD CATBUF+$23 ;LEN JSR SETPNT STADR FILES ;FPNT ACTLOOP DEC THISCNT BNE NXFIL DOS read ;RWPARMS BCS :CD ;Had eof JSR SETPNT BNE ISACT ;Always :CD JMP CATDONE SETPNT LDA ENTPER ;Get entries/block STA THISCNT ; and point to start STADR CATBUF+4 ;PNT RTS NXFIL LDA PNT ;Point to next file CLC ADC LEN STA PNT BCC ISACT INC PNT+1 ISACT LDY #0 LDA (PNT),Y BEQ ACTLOOP ;Branch if file not active * Process active file: AND #$F TAX ;Name length LDY #$10 LDA (PNT),Y CMP #$F BEQ ACTLOOP ;Ignore directories LDY #0 TXA STA (FPNT),Y ;Save name length ]LOOP INY LDA (PNT),Y ; and file name ORA #$80 STA (FPNT),Y DEX BNE ]LOOP JSR INCPNT ;Bump pointer LDA FPNT+1 CMP #>$BE00 BLT ACTLOOP ;Plenty of space CATDONE DOS close ;CLSPARMS LDY #0 TYA STA (FPNT),Y ;Mark end of catalog DECPNT LDA FPNT ; & point to last entry SEC SBC #$10 STA FPNT BCS :RET DEC FPNT+1 LDA FPNT+1 CMP #>FILES ;If backed up too far then BLT INCPNT ; go back where we were :RET RTS INCPNT LDA FPNT CLC ADC #$10 STA FPNT BCC :RET INC FPNT+1 :RET RTS *================= * MLI error tables *----------------- ERRORS HEX 27,2B,40,44,45,46,47,48,49,4A,FF,00 ERREND ERROFF DFB :IO-ERRORS DFB :WRTPROT-ERRORS DFB :INVPATH-ERRORS DFB :DIRNOT-ERRORS DFB :VOLNOT-ERRORS DFB :FILENOT-ERRORS DFB :DUP-ERRORS DFB :VOLFUL-ERRORS DFB :DIRFUL-ERRORS DFB :BADFORM-ERRORS DFB :TOOBIG-ERRORS DFB :BADBAS-ERRORS :IO ASC "I/O error"00 :WRTPROT ASC "Write protected"00 :INVPATH ASC "Invalid pathname"00 :DIRNOT ASC "Directory not found"00 :VOLNOT ASC "Volume not found"00 :FILENOT ASC "File not found"00 :DUP ASC "Duplicate filename"00 :VOLFUL ASC "Volume full"00 :DIRFUL ASC "Volume directory full"00 :BADFORM ASC "Incompatible file type"00 :TOOBIG ASC "File too large"00 :BADBAS ASC "Defect in BASIC program"00 ERR *-ERRORS/$100 PAG *======/A/ASM/SRC================================ * Header code written at start of file and called * at the end of EXEC to set pfx & file info. *------------------------------------------------ SETINF ORG $E00 SEC LDA CHKSUM BNE :SINF ERR *-$E05 CLD JSR CROUT LDA DEVNUM ;Set current unit for STA :ONLUNIT ; getting the vol name DOS getpfx ;:PFXP ORA IN+$80 ;Error or BNE :SINF ; use prefix if there DOS online ;:ONLP BCS :SINF LDA IN+$81 ;Else use volume name AND #$F TAX INX STX IN+$80 LDA #'/' STA IN+$81 DOS setpfx ;:PFXP :SINF LDX #:ERR-:ALL ;Prepare to send err msg BCS :MLIERR DOS setinfo ;PARMS-SETINF+$E00 BCS :MLIERR LDX #FILEINF-:ALL+FILENAME-NOWINF+1 JSR :PRINT TAX :MLIERR JSR :PRINT ;Print "error" or JMP DOSWARM ; "saved" :OUT JSR COUT INX :PRINT LDA :ALL,X BNE :OUT RTS :ALL ASC " saved"8D00 :ERR ASC "Error"878D00 :ONLP DFB 2 :ONLUNIT DFB 0 DA IN+$81 :PFXP DFB 1 DA IN+$80 FILEINF ORG NOWINF PARMS DFB 7 DA FILEINF+FILENAME-NOWINF ACC DFB 0 DFB 0 DA 0 ZERO DFB 0 DA 0 DA 0,0 PARMEND FILENAME DS $11 ;Need one 0 for stopper SIEND ERR SIEND-SETINF/$FF *======================================== * Decoder for 4-bit packing. This is * just a hex representation of the bytes. *---------------------------------------- READSQZ ORG $F00 CLD LDY #0 STY CHKSUM DEY STY PNT LDA #$F STA PNT+1 ;Will put code at LOADADR LOOP JSR GETLNZ ;Read a line of file LDY #0 LDX #-1 NXTBYTE JSR MAKNIB INCD PNT ASL ASL ASL ASL STA (PNT),Y ;Store in buffer LOADADR- JSR MAKNIB ORA (PNT),Y STA (PNT),Y EOR CHKSUM STA CHKSUM BCC NXTBYTE MAKNIB INX LDA IN,X ORA #$80 CMP #" " BEQ MAKNIB ;Skip spaces EOR #"0" ;Convert ascii digit CMP #10 ; to hex nibble. BLT :GOT ADC #$88 ORA #$20 CMP #$FA BGE :MASK PLA PLA CPX #4 BGE LOOP TYA STA (PNT),Y ;Zero checksum JMP MONITOR :MASK CLC ;Signal digit valid AND #$F :GOT RTS DFB 0,0 ;End of code marker ORG *============================================= * Decoder for 6-bit packed packing. Like reg * 6-bit packing but has special code with 1st * byte '0' next two the repeated byte (stored * 00000011 then 11111100) and last byte the * count-2/2, count always is even. *--------------------------------------------- RS6P ORG $F00 CLD LDY #0 STY CHKSUM STY PNT LDA #>LOADADR STA PNT+1 ;Will put code at LOADADR :LOOP JSR GETLNZ ;Read a line of file CPX #5 BLT :MON ;Next line till empty LDX #0 :NXTBYTE JSR :MAKNIB ;Get top 2 bits for STA TEMP ; next 3 bytes LDY #-1 ROR FLAG :UNPACK INY JSR :MAKNIB ;Get a data 6-bit nibble ASL TEMP ;Shift on its top 2 bits ROR ASL TEMP ROR STA (PNT),Y BIT FLAG BMI :SKIP EOR CHKSUM STA CHKSUM :SKIP CPY #2 BLT :UNPACK ;Loop till unpacked 3 bytes BIT FLAG BPL :TY ROL ;Top bits clr, carry set STA TEMP ;Count-1 DEY LDA (PNT),Y ASL ASL ;Clears carry DEY ORA (PNT),Y :STR STA (PNT),Y INY DEC TEMP ;Count down the repetition BPL :STR :TY TYA ADC PNT ;Bump pntr to next group STA PNT BCC :NXTBYTE INC PNT+1 BCS :NXTBYTE :NOTLEG PLA PLA BCC :LOOP :Always :MON JMP MONITOR ;Call monitor to do rest :MAKNIB INX LDA IN,X ASL CMP #' '*2 BEQ :MAKNIB ;Skip over spaces EOR #'0'*2 BEQ :RET EOR #'0'*2 SBC #$3F*2 BLT :NOTLEG ;Abort if not in range ASL ;Shift to top for easier :RET RTS ; unpacking DFB 0,0 ;End of code marker ORG *=============================== * Regular 6-bit decoder routine: *------------------------------- RS6 ORG $F00 CLD LDY #0 STY CHKSUM STY PNT LDA #>LOADADR STA PNT+1 ;Will put code at LOADADR :LOOP JSR GETLNZ ;Read a line of file CPX #5 BLT :MON LDX #0 :NXTBYTE JSR :MAKNIB ;Get top 2 bits for STA TEMP ; next 3 bytes LDY #-1 :UNPACK INY JSR :MAKNIB ;Get a data 6-bit nibble ASL TEMP ;Shift on its top 2 bits ROR ASL TEMP ROR STA (PNT),Y ;Store in buffer LOADADR- EOR CHKSUM STA CHKSUM CPY #2 BLT :UNPACK ;Loop till unpacked 3 bytes TYA ADC PNT ;Bump pntr to next group STA PNT ;Carry is set BCC :NXTBYTE INC PNT+1 BCS :NXTBYTE :MAKNIB INX LDA IN,X ASL CMP #' '*2 BEQ :MAKNIB ;Skip over spaces SBC #$3F*2 BLT :NOTLEG ;Abort if not in range ASL ;Shift to top for easier RTS ; unpacking :NOTLEG PLA PLA BLT :LOOP ;Next line, always taken :MON JMP MONITOR ;Call monitor to do rest DFB 0,0 ;End of code marker ORG ENDPRG ERR \$3000 DO SAVOBJ SAVE EXECUTIONER FIN