developer icon

Apple II DOS version 3.1

developer | PRO | 11/16/13 12:36:17 AM UTC | 0 ⭐ | 14713 👁️ | Never ⏰ | []
Basic4GL |

71.37 KB

|

None

|

0 👍

/

0 👎

    .TITLE  SHEP,’APPLE DOS’
*   6.3 10-6-78
*   8 BIT ASSEMBLER
    .M6502
*
**************************************************************************************
*   (C)  COPYRIGHT 1978  APPLE COMPUTER, INC
**************************************************************************************
ORG1    EQU $1B00
ORG2    EQU $3600
DISKIO  EQU $3D00
ASC1    EQU $3800
AEC1    EQU $3ABF
ASC2    EQU $3D00
AEC2    EQU $3FFF
EDOS    EQU $4000
    PAGE
    ORG ORG1
BEQIN   JMP DBINIT
;
DOSREL
;
;   GET RELOCATION PARMS
;
DR0
LOC1    EQU $26
    LDA #$BF        ; START AT BF00
    STA ZPGWRK+1        ; TO LOOK FOR
    LDX #0      ; HIGH RAM
    STX ZPGWRK
    LDY #0      ;APPLE TEST
DR1B
    LDA (ZPGWRK,X)
    STA LOC1
DR1 TYA
    EOR LOC1
    STA LOC1
    TYA
    EOR (ZPGWRK,X)
    STA (ZPGWRK,X)
    CMP LOC1
    BNE DR1A
    INY
    BNE DR1B
    BEQ DR2     ; BR IF TOOK
DR1A
    DEC ZPGWRK+1        ; NOT RAM
    BNE DR1     ; TRY NEXT PAGE
;
DR2
;   LDY ZPGWRK+1
    INY         ; NEW END OF DOS
    STY NEPAGE
    SEC
    TYA
    SBC DOSLNG      ; MINUS DOS LENGTH
    STA NSPAGE      ; IS NEW START OF DOS
    SEC
    SBC RSPAGE      ; MINUS OLD DOS START
    BEQ BEQIN       ; (BREIF NO DELTA)
    STA DELTA       ; IS DELTA
    PAGE
    LDA RSPAGE      ; RESET START PAGE TO NORMAL
    STA ASTART+1
;
    LDA #DBINIT/256 ;RESET PI RTN TO NORMAL
    STA DI3+2
    LDA #DBINIT&255
    STA DI3+1
;
;
    PAGE
;
;
;   RELOCATE ADR TABLES
;
    LDX #0
    STX ZPGWRK
DR3
    LDA ADRTAB+1,X
    TAY
    LDA ADRTAB+2,X
    STA ZPGWRK+1
    JMP DR5
;
DR4
    CLC
    LDA (ZPGWRK),Y
    ADC DELTA
    STA (ZPGWRK),Y
    INY
    BNE DR5
    INC ZPGWRK+1
DR5 INY
    BNE DR6
    INC ZPGWRK+1
;
DR6
    LDA ZPGWRK+1
    CMP ADRTAB+4,X
    BCC DR4
    TYA
    CMP ADRTAB+3,X
    BCC DR4
;
    TXA
    CLC
    ADC #4
    TAX
    CPX ADRTAB
    BCC DR3
    PAGE
;
;   RELOCATE CODE
;
    LDX #0
DR7 STX TEMP1
;
    LDA CDETAB+1,X  ; GET A START OF CODE ADR
    STA ZPGWRK      ; PUT IN ZPG
    LDA CDETAB+2,X
    STA ZPGWRK+1
;
DR8 LDX #0
    LDA (ZPGWRK,X)  ; GET OP CODE
    JSR INSDS2      ; GO FIND OUT HOW LONG
;
    LDY LENGTH      ; GET HOW LONG
    CPY #2      ; IF IT AIN’T
    BNE DR9     ; 3 THEN DON’T RELOC
    LDA (ZPGWRK),Y  ; GET PAGE FROM INST
    CMP RSPAGE      ; IF PAGE < REL START
    BCC DR9     ; THE IGNOR
    CMP REPAGE      ; IF PAGE >= REL END
    BCS DR9     ; THEN IGNORE
    ADC DELTA       ; ELSE ADD DELTA
    STA (ZPGWRK),Y  ; TO RELOCATE
;
DR9 SEC
    LDA LENGTH      ; ADD LENGTH
    ADC ZPGWRK      ; TO PC
    STA ZPGWRK
    LDA #0
    ADC ZPGWRK+1
    STA ZPGWRK+1
;
    LDX TEMP1       ; CHECK FOR END
    CMP CDETAB+4,X  ; OF CODE SEGMENT
    BCC DR8     ; BR NOT END
    LDA ZPGWRK
    CMP CDETAB+3,X
    BCC DR8     ; BR NOT END
;
    TXA 
    CLC
    ADC #4      ; INCREMENT TABLE INDEX
    TAX
    CPX CDETAB      ; DONE
    BCC DR7     ; BR IF NOT
;
    PAGE
;
;   MOVE TO RELOCATED CODE
;
    LDA #DEPAGE-1
    STA ZPGWRK+1        ; ZPGWRK=FROM
    LDY NEPAGE
    DEY
    STY ZPGFCB+1        ; ZPGFCB = TOO
    LDA #0
    STA ZPGWRK
    STA ZPGFCB
    TAY
;
DR10    LDA (ZPGWRK),Y  ; BYTE FROM
    STA (ZPGFCB),Y  ; BYTE TO
    INY         ; INCREMENT
    BNE DR10        ; BR NOT FULL PAGE
    DEC DPGCNT      ; DECREMENT PAGE CNT
    BEQ DR11        ; BR IF DONE
    DEC ZPGWRK+1        ; INC FROM PAGE
    DEC ZPGFCB+1        ; INC TOO PAGE
    BNE DR10        ; MOVE PAGE
;
DR11    JMP DBVECT+3        ; DONE
    PAGE
DEPAGE  EQU EDOS/256
DSPAGE  EQU START/256
INSDS2  EQU $F88E
LENGTH  EQU $2F
ADRTAB  DB  9*4
    DB  @@SAT1,@@EAT1
    DB  @@RUN,@@RUN+2
    DB  @@IBVT+2,@@IBVT+4
    DB  @@AS1VT,@@AS1VT+4
    DB  @@AS2VT,@@AS2VT+4
    DB  @@AS2VT+6,@@AS2VT+8
    DB  @@SAT2,@@EAT2
    DB  @@BAIOB,@@ADOSLD+2
    DB  @@IBDCTP,@@IBDCTP+2
    DB  @0,@0
    DB  @0,@0
    DB  @0,@0
CDETAB
    DB  6*4
    DB  @@SC1,@@EC1
    DB  @@SC2,@@EC2
    DB  @@SC3,@@EC3
    DB  SDP1,@@EDP1
    DB  ASC1,@@AEC1
    DB  @@ASC2,@@AEC2
    DB  @0,@0
;
RSPAGE  DB  DSPAGE
REPAGE  DB  DEPAGE
;
NSPAGE  DB  0
NEPAGE  DB  0
;
DOSLING DB  DEPAGE-DSPAGE
;
DELTA   DB  0
DPGCNT  DB  DEPAGE-DSPAGE
    PAGE
    BOUND   256 
;
;   RELOCATION  TABLES
;
START
SAT1
FTAB    DB  @@*-45      ;START OF FTABS
CINA    DB  @@CHRIN     ;CHAR IN ADR
COUTA   DB  @@CHROUT        ;CHAR OUT ADR
FN1ADR  DB  @@FNAME1
FN2ADR  DB  @@FNAME2
SVBLA   DB  @@SVBL
ASTART  DB  @@BEQIN     ;CHANGED TO START BY RELOCATE
CCBADR  DB  @@CCB
;
OUTSVT              ;CHAR OUTPUT STATE VECTOR TABLE
    DB  @@COS0-1
    DB  @@COS1-1
    DB  @@COS2-1
    DB  @@COS3-1
    DB  @@COS4-1
    DB  @@COS5-1
    DB  @@COS6-1
;               COMMAND EXECUTION TABLE
CMDETB
    DB  @@EINIT-1
    DB  @@ELOAD-1
    DB  @@ESAVE-1
    DB  @@ERUN-1
    DB  @@ECHAIN-1
    DB  @@EDEL-1
    DB  @@ELOCK-1
    DB  @@EUNLK-1
    DB  @@ECLOSE-1
    DB  @@EREAD-1
    DB  @@EEXEC-1
    DB  @@EWRITE-1
    DB  @@EPOS-1
    DB  @@EOPEN-1
    DB  @@EAPND-1
    DB  @@EREN-1
    DB  @@ECAT-1
    DB  @@EMON-1
    DB  @@ENOMON-1
    DB  @@EPR-1
    DB  @@EIN-1
    DB  @@EMAXF-1
    DB  @@EAS-1
    DB  @@EINT-1
    DB  @@EBSV-1
    DB  @@EBLD-1
    DB  @@EBRUN-1
    DB  @@EVAR-1
EAT1
 
        PAGE
;
;       NON-RELOCATING ADRS
;
IBASVT
CHAIN   DB  @@IBCHN
RUN DB  @@IBRUN
BREAK   DB  @@IBBRK
GO  DB  @@IBGO
CONT    DB  @@IBCONT        ;BASIC CONT ENTRY POINT
IBVT    DB  @@IBCHN,@@IBRUN,@@IBRK
 
    DB  @@IBGO,@@0
 
IBVTL   EQU *-IBVT
;
AS1VTL  DB  @@ASRUN1,@@ASRUN1,@@ASBRK1
 
    DB  @@IBGO,@@0
 
AS1VTL  EQU *-AS1VT
;
AS2VT   DB  @@ASRUN2,@@ASRUN2,@@ASBRK2
 
 
    DB  @@DBINIT,@@0
 
AS2VTL  EQU *-AS2VT
    PAGE
;
;   EQUATES REQD TO FIND THINGS IN APPLE II
;
SETVID  EQU $FE93
SETKBD  EQU $FE89
PROMPT  EQU $33     ;PROMPT CHAR
OUTSW   EQU $36     ;OUTPUT VECTOR SWITCH
INSW    EQU $38     ;INPUT VECTOR SWITCH
ZPGWRK  EQU $40     ;ZERO PAGE WORK CELL
CNUM    EQU $44     ;CONVERTED NUMERIC
LBUFF   EQU $200        ;LINE BUFFER
MULT    EQU $FB63       ;MULT ROUTINE
INPRT   EQU $FE8B       ;SET OUT PORT
OUTPRT  EQU $FE95       ;SET OUT PORT
IBCHN   EQU $E836       ;BASIC RUN
IBLMEM  EQU $4A     ;BASIC LOW MEMORY
IBHMEM  EQU $4C     ;INTEGER BASIC HIMEM
IBSOP   EQU $CA     ;INTEGER BASIC START OF CGM
IBBRK   EQU $3E3        ;BASIC BREAK
IBGO    EQU $E000       ;BASIC ENTRY POINT
IBCONT  EQU $E003       ;BASIC CONTINUE ENTRY POINT
IBSOV   EQU $CC     ;BASIC START OF VARIABLES
ASSOP   EQU $67     ;AS START OF PROGRAM
ASEOP   EQU $AF     ;AS END OF PROGRAM
ASEOP2  EQU $69     ;AS END-OF PGM 2
ASHM1   EQU $73     ;AS HIGH MEM 1
ASHM2   EQU $6F     ;AS HIGH MEM 2
ASLMEM  EQU $ASSOP      ;AS LOW MEM
ASBRK1  EQU $D865       ;AS ROM BREAK
ASBRK2  EQU $1067       ;AS RAM BREAK
AITSTL  EQU $E000       ;AS 1 IB TEST LOC
ATSTV   EQU $4C     ;AS TEST VALUE
ITSTV   EQU $20     ;IB TEST VALUE
BOOTSL  EQU $2E     ;BOOT FROM SLOT
ZPQFCB  EQU $42     ;ZERO PAGE WORK CELL
HOME    EQU $FC58
PRINT   EQU $FDED
GETKEY  EQU $FD0C
 
    PAGE
;
;   DOS BASIC INTERPRETER – INITIAL ENTRY
;
SC1
DBINIT
    LDA IBSLOT      ;GET BOOT SLOT
    LSRA
    LSRA
    LSRA
    LSRA
    STA CS      ;SET AS CURRENT SLOT
    LDA IBDRVN      ;GET BOOT DRIVE NUMBER
    STA CD      ;SET AS CURRENT DRIVE
    LDA AITSTL      ;GET APPLESOFT/IB TEST
    EOR #ITSTV      ;IF AS THEN
    BNE IAS1        ;GO TO AS INIT
;               ;ELSE INIT FOR IB
    STA ASIBSW      ;SET SW FOR IB
    LDX #IBVTL      ;GET IB VT LENGTH
IIB1    LDA IBVT-1,X        ;MOVE IB ADDR
    STA IBASVT-1,X
    DEX
    BNE
    JMP INITAA
;
IAS1
    LDA #$40        ;INDICATE ROM APPLESOFT
    STA ASIBSW
    LDX #AS1VTL
IAS1A   LDA AS1VT-1,X   ;MOVE ROM AS ADRS
    STA IBASVT-1,X
    DEX
    BNE IAS1A
;
INITAA
    SEC         ;INDICATE INIT
    BCS INITA
DBRST
    LDA ASIBSW      ;GET AS/IB FLAG
    BNE INITA1      ;BR IF NOT IB
    LDA #ITSTV      ;GET IB TEST VALUE
    BNE INITA2      ;GO SET IB
INITA1  ASLA            ;TST ROM AS
    BPL INITA3      ;BR IF NOT ROM TEST VALUE
    LDA #ATSTV      ;GET AS ROM TEST VALUE
INITA2  JSR SWTST       ;GO SET
INITA3
    CLC         ;INDICATE RESET
;
INITA
    PHP         ;SAVE INIT/RESET
    JSR MVCSW       ;GO MOVE CHAR SWITCH
    LDA #MC+MI+MO   ;SET MONITOR MODES
    STA MONMOD
;
    LDA #0
    STA OSTATE      ;CLEAR OUTSTATE AND EXECUTE STATE
    PLP         ;GET INSTATE
    RORA            ;SHIFT CARRY TO MSB
    STA ISTATE      ;SAVE INSTATE
    BMI INITB       ;BR IF INIT
    JMP (CONT)      ;GO TO CONTINUE ENTRY
INITB   JMP (GO)        ;GO TO GO ENTRY
 
    PAGE
INITC
    ASLA            ;OF ISTATE NOT ON
    BPL INITD       ;THEN NOT RAM AS
    STA ASIBSW      ;SET RAM AS
    LDX #AS2VTL
IAS2A   LDA AS2VT-1,X   ;MOVE RAM AS ADRS
    STA IBASVT-1.X
    DEX
    BNE IAS2A
    LDX #29
IAS2B   LDA FNAME2,X
    STA FNAME1,X
    DEX
    BPL IAS2B
;
INITD
    LDA DFNFTS      ;GO BUILD FILE TABS
    STA CNFTBS      ;AND SET MEM BOUNDS
    JSR BLDFTB
    LDA ESTATE      ;GET EXEC STATE
    BEQ INITZ       ;BR IF NOT EXECTUTE
    PHA         ;SVE CHAR
    JSR MVEFTA      ;GO MOVE EX FILE TAB ADR TO ZP
    PLA         ;GET SAVED CHAR
    LDY #0
    STA (ZPGWRK),Y  ;
INITZ
    JSR CLRSTS      ;SET IN AND OUT STATES TO ZERO
    LDX #IFBL
INITE   LDA DBVECT,X        ;MOVE RESTART VECTORS   
    STA $3D0,X
    DEX
    BPL INITE
    LDA CMDNO       ;IF NOT BOOT
    BNE INITF       ;THEN DONE
    LDA FNAME1      ;IF FN1
    EOR #$A0        ;NOT DONE
    BEQ INITF       ;THEN DONE
    JMP ERUN        ;ELSE
;
IFB
INITF
    LDA SVCMD
    BEQ INITG
    STA CMDNO
    JMP CMDGO
INITG
    JMP ORTN
;
DBVECT  JMP DBRST
    JMP DBINIT
    JMP DOSENT
    JMP DISKIO
CCBLDR
    LDA CCBADR+1
    LDY CCBADR
    RTS
 
IOBLDR
    LDA AIOB+1
    LDY AIOB
    RTS
IFBL    EQU *-IFB-1
 
    PAGE
;
;   CHRIN – CHAR RCVD VIA IN SWITCH
;
CHRIN
    JSR SVREGS
    LDA ISTATE      ;IF NOT DISKIN
    BEQ CHIN1       ;THEN BRANCH, ELSE
    BPL CHINO
    JMP INITC
CHINO
    LDA SVA
    STA ($28),Y
    JMP ICFD        ;AND GET CHAR FROM DISK
CHIN1
    LDA ESTATE
    BEQ CHIN2
    JMP NXTEXC
CHIN2
    LDA #3      ;SET OUT CHAR
    STA OSTATE      ;STATE TO INPUT ECHO
    JSR LDREGS
    JSR GETIN
    STA SVA
    JMP ORTN
;
GETIN   JMP (INSW)
;
;   CHROUT – CHAR RCVD VIA OUTPUT SWITCH
;
CHROUT
    JSR SVREGS      ;SAVE REGS
 
    LDA OSTATE      ;GET OUT SPARE
    ASLA
TAX
LDA OUTSVT+1,X  ;GET ROUTINE ADR
PHA
LDA OUTSVT,X
PHA
LDA SVA
RTS         ;GO TO ROUTINE
;
;   SVREGS – SAVE REGS WHILE PROCESSING CHARS
;
SVREGS
    STA SVA     ;SAVE ACU
SVRGSA
    STX SVX     ;SAVE X
    STY SVY     ;SAVE Y
    LDX #3      ;SET FOR FOUR BYTE MOVE
SVRB    LDA SVOUTS,X        ;MOVE SAVED OUT AND IN SW
    STA OUTSW,X     ;TO APPLE OUT/IN SW
    DEX
    BPL SVRB
    RTS         ;DONE
    PAGE
;
;   COS0 – 1ST CHAR OF PRINTED OUTPUT LINE
;       CHECK FOR CNTL-D
;
COS0
    LDX ISTATE      ;IS IN STATE NOT ZERO
    BEQ COS01
    CMP #’?+$80       ;THEN IS THIS?
    BEQ COS6        ;THEN PRINT ONLY IF MONITOR
    CMP PROMPT
    BEQ COS6
COS01
    LDX #2
    STX OSTATE
    CMP CCHAR       ;IF NOT CNTL-D
    BNE COS2        ;THEN GO TO STATE 2
    DEX
    STX OSTATE      ;ELSE STATE = 1
    DEX
    STX LBUFD       ;AND LBUFD=0
;
;   COS1 – ACCUMULATE CMD FROM PRINTED OUTPUT
;
COS1
    LDX LBUFD       ;GET LINE BUFF DISPL
COS1A   STA LBUFF,X     ;PUT CHAR IN BUFF
    INX         ;INCR PTR
    STX LBUFD       ;SAVE PTR
    CMP #$8D        ;WAS THIS A CR
    BNE CMDRTN      ;IF NOT THEN PR CHAR
;
    JMP SCNCMD      ;GO SCAN COMMAND
;
;   COS2 – PRINTED OUTPUT, NOT FIRST CHAR
;
COS2
    CMP #$8D        ;IS IT A CR
    BNE PRRTN       ;BR IF NOT
    LDX #0      ;SET FOR POSSIBLE C-D NEXT
    STX OSTATE      ;NEXT STATE
    JMP PRRTN       ;GO PRINT CHAR
    PAGE
;
;   COS3 – KEY IN ECHO PRINT
;
COS3
    LDX #0
    STX OSTATE      ;RESET OUT STATE
    CMP #$8D        ;IS IT CR
    BEQ COS3A       ;IS CR THEN CMD CHECK
COS3B
    LDA ESTATE      ;ELSE IF NOT EXECUTE
    BEQ PRRTN       ;THEN PRINT CHAR
    BNE DRTNI       ;ELSE PRINT IF MON INPUT
COS3A
;
    JSR TSTRUN
    BCS COS3B
    LDX SVX     ;GET LINE INDEX
    JMP COS1A
;
;   COS4 – DISK OUTPUT MODE
;
COS4
    CMP #$8D        ;IS IT CR
    BNE COS4A       ;BR IF NOT CR
    LDA #5      ;SET STATE FOR CNTL-D
    STA OSTATE      ;EXAMINE
COS4A   JSR OCTD        ;GO OUTPUT CHAR TO DISK
    JMP DRTNO       ;GO TO DATA RETURN (OUT)
;
;   COS5 – DISK OUTPUT MODE – 1ST CHAR OF A LINE
;
COS5
    CMP CCHAR       ;IS IT CNTL D
    BEQ COS0        ;BR IF CNTL– D
    CMP #$8A        ;LINE FEED?
    BEQ COS4A
    LDX #4
    STX OSTATE      ;SET NEW OUT STATE
    BNE COS4        ;BR IF NOT CNTL D
;
;   COS6 – DISK INPUT ECHO
;
COS6    LDA #0
    STA OSTATE      ;RESET OUT STATE = 0
    BEQ DRTNI       ;GO TO DATA IN RETURN
 
    PAGE
;
;   PRRTN – PRINT CHAR RETURN
;
;
;   CMDRTN – PRINT CHAR IF MONITOR CMBS MODE
;   DRTNO – PRINT CHAR IF MONITOR DATA OUT
;   DRTNI – PRINT CHAR IF MONITOR DATA IN
;
CERTN
    LDA LBUFF       ;CHECK FOR PRINTED COMMAND
    CMP CCHAR   
    BEQ CMDRTN      ;IF PC THEN NO RESET X REG
    LDA #$A0        ;BLANK
    STA LBUFF
    LDA #$8D        ;PLUS CR
    STA LBUFF+1     ;TO OUT BUFFER
    LDX #0      ;RESET TO SOL
    STX SVX
CMDRTN  LDA #MC
    BNE MODECK
DRTNO   LDA #MO
    BNE MODECK
DRTNI   LDA #MI
;
MODECK
    AND MONMOD      ;AND WITH MODE
    BEQ ORTN        ;BR IF NOT PRINT
PRRTN   JSR LDREGS
    JSR ORTN1
    STA SVA
    STY SVY
    STX SVX
;
ORTN
    JSR MVCSW       ;GO MOVE CHAR I/O SWITCH
LDREGS
    LDA SVA     ;ACU
    LDY SVY     ;Y
    LDX SVX     ;X
    SEC
    RTS         ;BY PASS PRINT
;
ORTN1   JMP (OUTSW)
;
;   PRCRIF – PRINT CR IF MON CMDS
;
PRCRIF
    BIT MONMOD      ;IF NOT MON CMDS
    BVC PRCIFR      ;THEN RETURN
    LDA #$8D        ;ELSE PRINT CR
    JSR ORTN1
PRCIFR  RTS
 
    PAGE
;
;   SCNCMD – SCAN COMMAND
;
SCNCMD
    LDY #$FF
    STY CMDNO       ;RESET COMMAND NUMBER
    INY
    STY SVCMD
SC0
    INC CMDNO       ;INCR CMD NO
    LDX #0      ;RESET LINE INDEX TO 0
    PHP         ;SAVE EQ STATUS
    LDA LBUFF,X     ;GET 1ST  LINE CHAR
    CMP CCHAR       ;IS IT CONTROL D
    BNE SC0A        ;BR /IF NOT
    INX         ;INCR OVER CNTLD
SC0A    STX LBUFD
;
SC1X
    JSR GNBC        ;GET NON BLANK INPUT CHAR
    AND #$7F        ;MSB OF CHAR OFF
    EOR CMDNTB.Y        ;EOR WITH INPUT
    INY         ;INCREMENT TABLE INDEX
    ASLA            ;IF MSB OF EOR RESULT ON
    BEQ SC1A        ;IF RESULT NOT NOW ZERO
    PLA         ;THEN INPUT DOES NOT
    PHP         ;EQUAL ENTRY
SC1A    BCC SC1X        ;LOOP FOR END ENTRY
;
    PLP         ;IF INPUT EQUALS END
    BEQ SYNTAX      ;THEN GO SYNTAX
;
    LDA CMDNTB,Y        ;IF NEXT TABLE CHAR NOT ZERO
    BNE SC0     ;THEN SCAN THE NEXT TABLE ENTRY
CNF             ;COMMAND NOT FOUND
    LDA LBUFF       ;LINE IS A CONTROL-D
    CMP CCHAR       ;THEN THIS IS A
    BEQ CNF1        ;POSSIBLE SYNTAX ERROR, ELSE
    JMP PRRTN       ;IT’S A BASIC INPUT LINE
CNF1
    LDA LBUFF+1     ;GET  NEXT CHAR
    CMP #$8D        ;IS IT A CR
    BNE CSERR       ;BR IF CR
    JSR CLRSTS      ;CLEAR THE STATES
    JMP CMDTRN      ;CNTL-D ONLY
;
CSERR   JMP ESYNTX
 
    PAGE
;
;   SYNTAX – FIGURE OUT WHAT WE GOT HERE
;
SYNTAX
    LDA CMDNO       ;CMDNO=CMDNO*2
    ASLA
    STA CMDNO
;
    TAY
    LDA #FN1
    AND CMDSTB,Y        ;IS FN1 REGD
    BEQ SN10        ;BR IF NOT 
    JSR CLRFNS
    PHP         ;SAVE EG STATUS
;
SN2
    JSR GNBC        ;GET NON BLANK CHAR
    BEQ SN6     ;BR IF CR OR COMMA
    ASLA            ;TEST FOR ALPHA
    BCC SN2A        ;BR IF ALPHA
    BMI SN2A        ;BR IS ALPHA
    JMP CNF     ;LURCH IF NOT ALPHA
SN2A    RORA            ;RESTORE BITS
    JMP SN4     ;AWAY WE GO
SN3 JSB GNXTC       ;GO GET NEXT CHAR
    BEQ SN6     ;BR IF COMMA OR CHAR
SN4 STA FNAME1,Y        ;PUT INTO ILENAME
    INY         ;INC FN INDEX
    CPY #60     ;ATFN FN INDEX
    BCC SN3     ;BR IF NOT
SN5 JSR GNXTC       ;LOOP UNTIL CR OR COMMA
    BEQ SN5
;
SN6 PLP         ;WAS THIS FN2 L OO
    BNE SN7     ;BR IF IT WAS
;
    LDY CMDNO
    LDA #FN2
    AND CMDSTB,Y        ;IF FN2 NOT REGD THEN
    BEQ SN8     ;BRANCH
;
    LDY #30     ;SET FN2 INDEX
    PHP         ;INDICATE FN2 SEEK
    BNE SN2     ;GO LOOK FOR FN2
;
SN7 LDA FNAME2      ;IF 1ST CHAR OF
    CMP #$A0        ;FN2 IS BLANK THEN
    BEQ SERR1       ;SYNTAX ERROR
;
SN8 LDA FNAME1      ;IF 1ST CHAR OF
    CMP #$A0        ;FN1 IS NOT BLANK
    BNE SOPTS       ;THEN GO LOOK FOR OPTIONS
;
    LDY CMDNO
    LDA #NPB+NPE        ;IF CMD MUST HAVE FILENAME
    AND CMDSTB,Y        ;THEN
    BEQ SERR1       ;THIS IS ERROR ELSE
;
    BPL SOPTS       ;ITS EXECUTABLE WITHOUT
;
SERR1   JMP CNF
;
CLRFNS
    LDA #0
    LDY #60
CLRFNA
    LDA #$A0
SN1 STA FNAME1-1,Y  ;CLEAR FN1, FN2
    DEY 
    BNE SN1
    RTS
 
    PAGE
SN10                ;FILE NAMES NOT REGD
    STA FNAME1
    LDA #NUM1+NUM2  ;IF NEITHER NUM1
    AND CMDSTB,Y        ;OR NUM2 IS REGD
    BEQ SOPTS       ;THEN GO LOOK AT OPTIONS
;
    JSR GETNUM      ;GO GET NUMERICS
    BCS SERR1
;
    TAY         ;IF HIGH DIGIT NOT
    BNE SERR1       ;ZERO THEN BAD
;
    CPX #17     ;IF LOW DIGIT GT 16
    BCS SERR1       ;THEN BAD
;
    LDY CMDNO
    LDA #NUM1
    AND CMDSTB,Y        ;IF WE WANT NUM2
    BEQ SN11
;
    CPX #8      ;IF NUM2>1
    BCS SERR1       ;THEN ERROR, ELSE
    BCC SOPTS       ;GO SCAN OPTIONS
;
SN11
    TXA         ;IF NUM1=0
    BEQ SERR1       ;THEN ERROR, ELSE
;
    PAGE
;
;   SOPTS – LOOK FOR SYNTAX OPTIONS
;
SOPTS
    LDA #0
    STA INOPTS      ;CLEAR INPUT OPTIONS
    STA IMBITS
    STA CL
    STA CL+1
    LDA LBUFD       ;SET PASS 1
    STA TEMP1A
;
SP1 JSR GNBC        ;GO GET NON-BLANK CHAR
    BNE SP2     ;BR IF NOT COMMA OR CR
    CMP #$8D        ;IF CHAR IS COMMA
    BNE SP1     ;THEN GO GET CHAR
;
    LDX CMDNO       ;OPTIONS INPUT = I
    LDA INOPTS      ;ALLOW OPTS = A
    ORA CMDSTB+1,X  ;IF (A OR I)
    EOR CMDSTB+1,X  ;XOR A NOT = 0 THEN
    BNE SERR1       ;WE HAVE UNALLOWED OPTIONS
;
    LDX TEMP1A      ;IF THIS IS PASS 2
    BEQ CMDGO       ;THEN DONE,
    STA TEMP1A      ;ELSE SET PASS
    STX LBUFD       ;RESTORE LBUFD AND
    BNE SP1     ;GO DO PASS 2
;
SP2 LDX #OPT1L      ;COMPARE CHAR HAVE WITH
SP3 CMP OPTAB1-1,X  ;CHARS IN OPT TABLE
    BEQ SP4     ;IF NOT FOUND CONTINUE
    DEX
    BNE SP3     ;IF NOT FOUND
    BEQ SERR2       ;THEN SYNTAX ERROR
;
SP4 LDA OPTAB2-1,X  ;IF CORRESPONDING OP TAB 2 IS
    BMI SP8     ;MINUS THEN IT MONITOR BITS
    ORA INOPTS
    STA INOPTS
    DEX
;
    STX TEMP2A      ;ELSE A NUMERIC MUST FOLLOW
    JSR GETNUM      ;FOLLOW
    BCS SERR2
;
    LDA TEMP2A      ;GET IOTION NUMBER
    ASLA            ;MULT BY 4
    ASLA
    TAY
;
    LDA CNUM+1      ;IF RESULT NUM HI IS
    BNE SP5     ;GT 0, THEN GT LOW RANGE
    LDA CNUM        ;TEST RESULT LOW
    CMP OPTAB3,Y        ;WITH LOW RANGE (LOW)
    BCC SERR2       ;BR IF RESULT < LR
    LDA CNUM+1
SP5 CMP OPTAB3+3,Y  
    BCC SP6     ;BR IF LESS
    BNE SERR2       ;BR IF GRREATER
    LDA CNUM
    CMP OPTAB3+2,Y
    BCC SP6     ;BR IF LESS
    BNE SERR2       ;BR IF GREATER
;
SP6 LDA TEMP1A      ;IF PASS 1,THEN
    BNE SP1     ;DON’T STORE RESULT
    TYA
    LSRA
    TAY
;
    LDA CNUM+1      ;STORE THE RESULT
    STA CUROPT+1,Y
    LDA CNUM
    STA CUROPT,Y
SP7 JMP SP1     ;GO FOR NEXT OPT
;
SP8             ;MONITOR REG
    PHA         ;SAVE TYPE REG
    LDA #CIO        ;SET OPTION OF CIO
    ORA INOPTS
    STA INOPTS
    PLA         ;RESTORE REG
    AND #$7F        ;CLEAR CIO
    ORA IMBITS      ;OR WITH PREV IMBITS
    STA IMBITS
    BNE SP7     ;GO FOR NEXT
;
SERR2   JMP CNF
 
    PAGE
;
;   CMDGO – EXECUTE COMMAND
;
CMDGO
    JSR CLRSTS
    JSR CLRCCB      ;GO CLEAR CCB
    JSR ECMD        ;GO EXECUTE
    JMP CERTN
ECMD
    LDA CMDNO       ;COMMAND NO
    TAX         ;IS CMD EXEC TAB INDEX
    LDA CMDETB+1,X  ;GET CMD ADR
    PHA         ;ONTO STACK
    LDA CMDETB,X
    PHA
    RTS         ;AND GOTO COMMAND
;
;   GNXTC – GET NEXT CHAR
;
GNXTC
    LDX LBUFD
    LDA LBUFF,X     ;GET NEXT CHAR AND IF
    CMP #$8D        ;IT IS A CR
    BEQ GNXTCR      ;THEN RETURN WITHOUT
    INX         ;INCR TO NEXT CHAR
    STX LBUFD
    CMP #’,+$80       ;TEST FOR COMMA
GNTXR   RTS
;
;   GNBC – GET NON BLANK CHAR
;
GNBC
    JSR GNXTC       ;GO GET NEXT CHAR
    BEQ GNXTCR      ;BR IF COMMA OR CR
    CMP #$A0        ;IS IT BLANK
    BEQ GNBC        ;BR IF BLANK
    RTS         ;DONE
;
;   CLRCCB – CLEAR CCB
;
CLRCCB
    LDA #0
    LDY #CCBLEN     ;CCBLENGTH
CLC1    STA CCB-1,Y     ;CLEAR BYTE
    DEY
    BNE CLC1
    RTS
 
    PAGE
;
;   GETNUM – COVERT ASCII INPUT TO NUMERIC
;
GETNUM
    LDA #0      ;CLEAR WORK AREA
    STA CNUM
    STA CNUM+1
    JSR GNBC
    PHP
    CMP #$A4
    BEQ HEXNUM
    PLP
    JMP GN2A
;
GN2 JSR GNBC        ;GET NEXT NON BLANK
GN2A
    BNE GN3     ;BR NOT COMMA OR CR
    LDX CNUM        ;X=RESULT LOW
    LDA CNUM+1      ;Y=RESULT HI
    CLC
    RTS         ;DONE
;
GN3 SEC
    SBC #$B0        ;SUBTRACT ASCII 0
    BMI GN4     ;BR IF NOT NUM
    CMP #10
    BCS GN4     ;BR IF NOT NUM
    JSR GN5     ;OLD*2
    ADC CNUM        ;PLUS NEW
    TAX
    LDA #0
    ADC CNUM+1
    TAY
    JSR GN5     ;OLD*4
    JSR GN5     ;OLD*8
    TXA         ;OLD*8 + OLD*2 + NEW
    ADC CNUM
    STA CNUM        ;=OLD*10 + NEW
    TYA
    ADC CNUM+1
    STA CNUM+1
    BCC GN2
;
GN4
    SEC
    RTS         ;DONE
GN5
    ASL CNUM        ;CNUM * 2
    ROL CNUM+1
    BCS GN4
    RTS
 
    PAGE
;
HEXNUM
    PLP
HNO
    JSR GNBC        ;GO GET CHAR
    BEQ GN2A        ;BR IF CR OR COMMA
;
    SEC
    SBC #$B0        ;CHAR – ASCII0
    BMI GN4     ;BR IF LTO
    CMP #10     ;IS IT LT10
    BCC HN1     ;BR IF LT
    SBC #$7     ;SUB 7 FOR ASCII A
    BMI GN4     ;BR IF LT A
    CMP #16     ;TEST GT 15
    BCS GN4     ;BR GT 15
HN1 JSR GN5     ;OLD*2
    JSR GN5     ;OLD*4
    JSR GN5     ;OLD*8
    JSR GN5     ;OLD*16
    ORA CNUM        ;OR IN NEW
    STA CNUM        ;SAVE NEW
    JMP HN0     ;GO FOR NEXT CHAR
 
    PAGE
;
;   EPR – EXECUTE PR#
;
EPR
    LDA CNUM        ;GET PORT
    JMP OUTPRT      ;GO DO IT
;
;   EIN – EXECUTE IN#
;
EIN
    LDA CNUM        ;GET PORT
    JMP INPRT       ;GO DO IT
;
;   EMON – EXECUTE MONITOR CMD
;
EMON
    LDA MONMOD      ;GET CURRETN BITS
    ORA IMBITS      ;OR IN NEW BITS
    STA MONMOD      ;SET NEW MODE
    RTS
;
;   ENOMON – EXECUTE NO MONITOR CMD
;
ENOMON
    BIT IMBITS
    BVC ENM1
    JSR PRCRIF
ENM1
    LDA #$70
    EOR IMBITS      ;INVERT INPUT BITS
    AND MONMOD      ;AND WITH CURRENT
    STA MONMOD      ;SET NEW MODE
    RTS
 
    PAGE
;
;   EMAXF – EXECUTE MAX FILES
;
EMAXF
    LDA #0      ;RESET EXECUTE
    STA ESTATE
    LDA CNUM        ;SAVE NEW NO FILES
    PHA
    JSR CLALL       ;GO CLOSE ALL TBLS
    PLA
    STA CNFTBS      ;SET NEW NO FILE TBLS
    JMP BLDFTB      ;GO BUILD NEW ONES
;
;   EDEL – DELETE A FILE
;
EDEL
    LDA #CRGDEL     ;DELETE REQUEST
    JSR OPEN        ;GO OPEN
    JSR FILSRC      ;FIND FILE
    LDY #0
    TYA
    STA (ZPGWRK),Y  ;RESET FN
    RTS
;
;   ELOCK – LOCK A FILE
;
ELOCK
    LDA #CRGLCK     ;SET LOCK
    BNE ELGO
;
;   EUNLK – UNLOCK A FILE
;
EUNLK
    LDA #CRGUNL     ;SET UNLOCK
ELGO
    JSR OPEN        ;OPEN FILE & UNLOCK
    JSR TSTFNF
    JMP ECLOSE
;
;   EVAR – VERIFY A FILE
;
EVAR
    LDA #CRGVAR     ;SET VARIFY
    BNE ELGO
 
    PAGE
;
;   EREN – RENAME A FILE
;
EREN
    LDA FN2ADR      ;MOVE FILE NAME2
    STA CCBFN2
    LDA FN2ADR+1
    STA CCBFN2+1
    LDA #CRGRNM
    STA TEMP1A      ;SET RENAME
    JSR EO3     ;GO OPEN AND RENAME
    JMP ECLOSE      ;GO CLOSE
;
;   EAPND – OPEN FILE FOR APPEND
;
EAPND
    JSR EOPEN       ;GO OPEN
    LDA #CREFNF
    CMP CCBSTA      ;IF FILE CREATED
    BNE AP1
    RTS
AP1
    JSR RBYTE       ;READ A BYTE
    BNE AP1     ;BR IF NOT ZERO
;
    JMP RWP3        ;GO RE-POSITION
 
    PAGE
;
;   EOPEN – OPEN A FILE
;
EOPEN
    LDA #CRGOPN
OPEN
    STA TEMP1A
    LDA CL      ;IF NO LENGTH ENTERED
    BNE EO1     ;THEN SET DEFAULT OF 1
    LDA CL+1
    BNE EO1
    LDA #1
    STA CL
EO1
    LDA CL      ;MOVE REC LENGTH
    STA CCBRLN
    LDA CL+1
    STA CCBRLN+1
EO3
    JSR ECLOSE      ;GO CLOSE IF OPEN
EO4
    LDA CNUM+1      ;GET AVALL ENTRY
    BNE EO5     ;BR IF ONE AVAIL
    JMP ENFA        ;DONE – NO FILES AVAIL
EO5
    STA ZPGWRK+1        ;MOVE AVAIL SLOT TO ZPG
    LDA CNUM
    STA ZPGWRK
EO6
    JSR MVFN1       ;GO MOVE FILE NAME
    JSR MVBUFP      ;GO MOVE BUF PTRS
    JSR OPNSUP      ;GO SET UP OPEN
    LDA TEMP1A      ;SET OPEN REG
    STA CCBREG
    JMP DOSGO       ;GO OPEN
 
    PAGE
 
;
;   ECLOSE – EXECUTE CLOSE FILE COMMAND
;
ECLOSE
    LDA FNAME1
    CMP #$A0
    BEQ CLALL
    JSR FILSRC      ;GO FIND FILE
    BCS ECL1        ;BR IF NOT FOUND
    JSR CLOSE       ;GO CLOSE
    JMP ECLOSE      ;GO SEE IF ANY MORE OPEN
ECL1    RTS
;
;   CLOSE – CLOSE A FILE
;
CLOSE
    JSR TSTEXC
    BNE CLX
    LDA #0
    STA ESTATE
CLX
    LDY #0      ;CLEAR 1ST FN
    TYA         ;CHAR TO ZERO
    STA (ZPGWRK),Y
    JSR MVBUFP      ;MOVE BUFFER PTRS
    LDA #CRGCLS     ;SET CLOSE
    STA CCBREG
    JMP DOSGO       ;GO CLOSE
;
;   CLALL – CLOSE ALL FILES
;
CLALL
    JSR TSINIT      ;GO INIT FILE SEARCH
    BNE CL1
CL0
    JSR TSNXT       ;NEXT ENTRY
    BEQ CL2     ;BR IF NO MORE
CL1
    JSR TSTEXC
    BEQ CL0
    JSR TSTOPN      ;GOL TEST OPEN
    BEQ CL0     ;BR NOT OPEN
    JSR CLOSE       ;GO CLOSE
    JMP CLALL       ;START OVER
CL2 RTS         ;DONE
 
    PAGE
;
;   EBSV – EXECUTE BINARY SAVE
;
EBSV
    LDA #A+L        ;IF ALL
    AND INOPTS
    CMP #A+L    
    BEQ EBSV1
    JMP CNF     ;THEN ERROR
EBSV1
    LDA #4      ;SET BINARY FILE
    JSR SV1     ;GO OPEN & TEST
    LDA CA+1        ;OUTPUTADR OF BLOCK
    LDY CA
    JSR SV2
    LDA CL+1        ;GO OPEN AND TEST
    LDY CL
    JSR SV2     ;OUTPUT LENGTH
    LDA CA+1        ;GET ADR GIVEN
    LDY CA
    JMP SV3     ;OUTPUT BLOCK
;
;   EBLD – EXECUTE BINARY LOAD
;
EBLD
    JSR EOPEN
    JSR TSTFNF
EBLD2
    LDA #$7F
    AND CCBFUC
    CMP #4
    BEQ EBLD3
    JMP ENBF
EBLD3
    LDA #4      ;SET BINARY FILE
    JSR SV1     ;GO OPEN $ TEST
    JSR LD2     ;GO GET ADR
    TAX
    LDA INOPTS
    AND #A      ;IF ADR NOT GIVEN
    BNE EBLD1
    STX CA      ;THEN USE ADR FROM FILE
    STY CA+1
EBLD1
    JSR LD2     ;GET LENGTH
    LDX CA      ;GET GIVEN ADR
    LDY CA+1
    JMP LD3     ;GO GET BLOCK
;
;   EBRUN – EXECUTE BINARY RUN
;
EBRUN
    JSR EBLD        ;GO LOAD FILE
    JSR MVCSW       ;GO RESTORE CHAR I/O SW
    JMP (CA)        ;GO EXEC THE STUFF
TSTFNF  LDA #CREFNF     ;FILE NOT FOUND ERROR CODE
    CMP CCBSTA      ;TEST FILE NOT FOUND
    BEQ FNF     ;BR IF FILE NOT FOUND
    RTS         ;FILE FOUND, RETURN
FNF JMP KLUTZ       ;GO FIX THINGS
 
    PAGE
;
;   ESAVE – EXECUTE SAVE REQUEST
;
ESAVE
    LDA ASIBSW      ;IF IB THEN
    BEQ EIBSV       ;GO TO IB SAVE
    LDA #2      ;GET APPLESOFT PGM
    JSR SV1     ;GO OPEN AND TEST
;
    SEC         ;BLOCK LENGTH
    LDA ASEOP       ;=EOP-SOP
    SBC ASSOP
    TAY
    LDA ASEOP+1
    SBC ASSOP+1
    JSR SV2     ;GO OUTPUT BLOCK
;
    LDA ASSOP+1     ;BLOCK ADR
    LDY ASSOP       ;=SOP
    JMP SV3     ;GO OUTPUT BLOCK
;
EIBSV
    LDA #1      ;SET IB PGM
    JSR SV1     ;GO OPEN AND TEST
;
    SEC         ;BLOCK LENGTH
    LDA IBHMEM      ;=HIMEM-SOP
    SBC IBSOP
    TAY
    LDA IBHMEM+1
    SBC IBSOP+1
    JSR SV2     ;GO OUTPUT LENGTH
;
    LDA IBSOP+1     ;BLOCK ADR
    LDY IBSOP       ;=SOP
    JMP SV3     ;GO OUTPUT
;
SV1
SV1A
    STA CCBFUC      ;SET BLOCK  PGM TYPE
    PHA         ;SAVE PGM TYPE
    JSR EOPEN       ;GO OPEN FILE
    PLA         ;GET SAVE TYPE
    JMP TSTFUC      ;GO CHECK
;
SV2
    STY CCBBLN      ;SET BLOCK LENGTH
    STY CCBDAT      ;AND DATA BYTE
    STA CCBBLN+1
    LDA #CRGWR      ;INDICATE WRITE
    STA CCBREG
    LDA #CRMNBT     ;NEXT BYTE
    STA CCBRQM
    JSR DOSGO       ;GO WRITE
    LDA CCBBLN+1        ;OTHER BYTE TOO
    STA CCBDAT
    JMP DOSGO
;
SV3 STY CCBBBA      ;SET BLOCK ADR
    STA CCBBBA+1
    LDA #CRMNBL     ;INDICATE BLOCK I/L
    STA CCBRQM
    JSR DOSGO       ;GO DO IT
    JMP ECLOSE      ;CLOSE FILE
 
    PAGE
NBPER   JMP ERNU1
;
;   ELOAD – EXECUTE LOAD REQUEST
;
ELOAD
    JSR CLALL       ;GO CLOSE ALL
    JSR EOPEN       ;OPEN FILE
    LDA #CREFNF
    CMP CCBSTA      ;WAS FILE FOUND
    BNE ELD1        ;BR IF FOUND
;
KLUTZ   JSR EDEL        ;DELETE NEW FILE
    LDA #CREFNF     ;FILE NOT FOUND MSG
    JMP ERROR       ;GO
;
ELD1
    LDA #$7F        ;MASK PROTECT BIT
    AND CCBFUC      ;OUT OF FUC
    BEQ NBPER       ;BR IF ERROR
    AND #$03        ;ISOLOLATE IB & AS
    BEQ NBPER       ;BR IF ERROR
    STA CCBFUC      ;SAVE IB/AS ONLY
    LDA ASIBSW      ;IF IB THEN
    BEQ EIBL        ;GO TO IB LOAD
    LDA #2
    JSR LD1     ;GO OPEN AND TEST
;
    JSR LD2     ;GO GET BLOCK LENGTH
;
    CLC
    ADC ASSOP       ;ADD BLOCK LENGTH TO SOP
    TAX
    TYA
    ADC ASSOP+1
;
    CMP ASHM1+1     ;IF BL+SOP >=HMEM
    BCS MFULL       ;THEN WON’T FIT
;
EASL1
    STA ASEOP+1     ;SET NEW EOP ADR
    STA ASEOP2+1
    STX ASEOP
    STX ASEOP2
    LDX ASSOP       ;GET ADR WHERE TO LOAD
    LDY ASSOP+1
    JMP LD3     ;GO LOAD
;
EIBL
    LDA #1      ;SET IB PGM
    JSR LD1     ;GO OPEN AND TEST
;
    JSR LD2     ;GO GET BLOCK LENGTH
;
    SEC         ;HMEM – BLOCK LENGTH
    LDA IBHMEM      ;IS NEW SOP
    SBC SVBL
    TAX
    LDA IBHMEM+1
    SBC SVBL+1
    BCC MFULL
    TAY
;
    CPY IBLMEM+1        ;IF NEW SOP <= LMEM
    BCC MFULL
    BEQ MFULL
    STY IBSOP+1     ;SET NEW SOP
    STX IBSOP
    JMP LD3
;
LD2
    LDA SVBLA       ;MOVE ADR OF WHERE
    STA CCBBBA      ;TO PUT DATA TO
    LDA SVBLA+1     ;CCBN
    STA CCBBBA+1
    LDA #0
    STA CCBBLN+1        ;READ INTO
    LDA #2
    STA CCBBLN
    LDA #CRGRD      ;READ
    STA CCBREG
    LDA #CRMNBL     ;BLOCK
    STA CCBRQM
    JSR DOSGO
    LDA SVBL+1
    STA CCBBLN+1
    TAY
    LDA SVBL
    STA CCBBLN
    RTS
;
LD3
    STX CCBBBA      ;SET BLOCK ADR
    STY CCBBBA+1
    JSR DOSGO       ;GEET BLOCK
    JMP ECLOSE      ;GO CLOSE FILE
;
MFULL
    JSR ECLOSE      ;GO CLOSE FILE
    JMP MFERR       ;AND GIVE ERR MSG
LD1
    CMP CCBFUC      ;TEST TYPE
    BEQ LD1C        ;BR IF MATCH
    LDX CMDNO
    STX SVCMD
    LSRA
    BEQ LD1A        ;BR IF PGM IS AS
    JMP EINT        ;GO FOR INTO BASIC
;
LD1A
    LDX #29     ;SAVE FILE NAME
LD1B    LDA FNAME1,X        ;INCASE IS RAM APPLESOFT
    STA FNAME2,X    
    DEX
    BPL LD1B
    JMP EAS     ;GO FOR AS
;
LD1C    RTS
 
    PAGE
;
;   ERUN – EXECUTE RUN REQUEST
;
ERUN
    JSR ELOAD       ;LOAD PGM
    JSR PRCRIF
    JSR MVCSW       ;GO RESTORE CHAR I/O SW
    JMP (RUN)
;
;   IBRUN – INT BASIC RUN
;
IBRUN
    LDA IBLMEM      ;RESET START OF VARS
    STA IBSOV
    LDA IBLMEM+1
    STA IBSOV+1
    JMP (CHAIN)
;
;   EHCAIN – EXECUTE CHAIN REQUEST
;
ECHAIN
    JSR ELOAD       ;LOAD PGM
    JSR PRCRIF
    JSR MVCSW       ;GO RESTORE CHAR I/O SW
    JMP (CHAIN)
ASRUN1  JSR $D665       ;ROM
    JMP $D7D2
ASRUN2  JSR $E65        ;RAM
    JMP $FD4
 
    PAGE
;
;   EWRITE – WRITE CMD EXECUTE
;
EWRITE
    JSR RWPOSN      ;GO POSITION FILE IF REGD
    JSR TSTFNF
    LDA #5
    STA OSTATE      ;SET OSTATE=5
    JMP CERTN       ;DONE
;
;   EREAD – READ COMD EXECUTE
;
EREAD
    JSR RWPOSN      ;GO POSITION FILE IF REGD
    LDA #1
    STA ISTATE      ;SET ISTATE = DISK INPUT 
    JMP CERTN       ;DONE
;
;   RWPOSN – POSITION FOR READ/WRITE
;
RWPOSN
    JSR FILSRC      ;FIND THE FILE
    BCC RWP1        ;BR IF FILE FOUND
    JSR EOPEN       ;GO OPEN FOR KLUTZ
    JMP RWP2        ;THEN SKIP NEXT LINE
RWP1
    JSR MVBUFP      ;MOVE BUFF POINTERS
RWP2
    LDA INOPTS      ;GET IN OPTIONS
    AND #R+B        ;WAS IT B OR R
    BEQ RWPR        ;BR IF NOT
    LDX #3
RWP2A   LDA CR,X        ;MOVE REL REC
    STA CCBRRN,X        ;AND REL BYTE
    DEX
    BPL RWP2A
RWP3
    LDA #CRGPOS     ;INDICATE POSITION REQUIRED
    STA CCBREG
    JSR DOSGO
RWPR    RTS         ;DONE
    PAGE
;
;
;   EINIT – EXECUTE INIT COMMAND
;
EINIT
    LDA #V      ;MUST HAVE
    AND INOPTS      ;VOL OPTION
    BEQ INER
    LDA CV
    BEQ INER        ;BE GT 0
    LDA ASTART+1
    STA CCBBSA
    LDA #CRQFMT
    JSR OPEN
    JMP ESAVE
;
INER    JMP CNF
;
;   ECAT – PRINT CATALOG
;
ECAT
    LDA #CRGDIR
    JSR OPEN        ;GO PRETEND OPEN
    LDA CCBVOL
    STA CV
    RTS
    PAGE
;
;   EAS – EXECUTE APPLESOFT REQUEST
;
EAS
    LDA #ATSTV      ;GET APPLESOFT TEST VALUE
    JSR SWTST       ;GO SWITCH AND TEST
    BEQ GOINIT      ;GO SWITCH AND TEST
    LDA #0
    STA ASIBSW
;
EAS0
    LDY #30
    JSR CLRFNA
    LDX #FASBL
EAS1    LDA FASB-1,X        ;MOVE SYSTEM FILE NAME
    STA FNAME1-1,X
    DEX
    BNE EAS1
;
EAS2
    LDA #$C0
    STA ISTATE      ;FOR RAM APPLESOFT
    JMP ERUN        ;GO LOAD AND RUN
;
;   EINT – EXECUTE INTEGER REQUEST
;
EINT
    LDA #ITSTV      ;GET IB TEST VALUE
    JSR SWTST       ;GO SWITCH AND RUN
    BNE EAS     ;BR IF NOT IB
GOINIT
    JMP DBINIT      ;GO INIT DOS
SWTST
    CMP AITSTL      ;TEST CURRENT VALUE
    BEQ SWTR
    STA $C080       ;TRY SWITCH 1
    CMP AITSTL      ;TEST AGAIN
    BEQ SWTR        ;BR IF NOW SAME
    STA $C081       ;TRY SWITCH 2
    CMP AITSTL      ;TEST AND
SWTR    RTS
;
    PAGE
;
;   EEXEC – EXEC CMD
;
EEXEC
    JSR EOPEN       ;OPEN FILE
    JSR TSTFNF
    LDA CFTABA      ;MOVE TABLE POINTERS
    STA EFTABA
    LDA CFTABA+1
    STA EFTABA+1
    LDA FNAME1      ;USE FILENAME
    STA ESTATE      ;SET EX STATE NON ZERO
    BNE EXP2
;
;
;   EPOS – EXECUTE POSITION
;
EPOS
    JSR FILSRC
    BCC EXP1
    JSR EOPEN
    JSR TSTFNF
    JMP EXP2
EXP1    JSR MVBUFP
EXP2
    LDA INOPTS      ;GET OPTIONS
    AND #R      ;TEST R
    BEQ EX2     ;BR NOT R
;
EXO LDA CR      ;IF CR NOT ZERO
    BNE EX1A        ;THEN DECREMENT
    LDX CR+1
    BEQ EX2
    DEC CR+1
EX1A    DEC CR
EX1 JSR RBYTE       ;AND READ A RCORD
    BEQ ICFD4
    CMP #$8D        ;UNTIL CR
    BNE EX1
    BEQ EX0     ;THEN TEST CR AGAIN
;
EX2 RTS         ;DONE
    PAGE
;
;   OCTD – OUTPUT A CHAR TO DISK
;
OCTD
    JSR TSTRUN      ;GO TEST RUN
    BCS ICFDB
    LDA SVA     ;CHAR IN SAVED ACU
    STA CCBDAT      ;PUT INTO CCBDATA AREA
    LDA #CRQWR      ;SET WRITE
    STA CCBREQ
    LDA #CRMNBT     ;SET NEXT BYTE
    STA CCBRQM
    JMP DOSGO       ;GO WRITE BYTE
;
;   INCFD – INPUT A CHAR FROM DISK
;
ICFD
    JSR TSTRUN      ;GO TEST RUN
    BCS ICFDB
    LDA #6      ;SET OUT STE = 6
ICFD3
    STA OSTATE      ;TO CATCH ECHO
    JSR RBYTE
    BNE ICFD1       ;BR IF NOT ZERO CHAR
ICCFD2
    JSR CLOSE
    LDA #3
    CMP OSTATE
    BEQ ICFD0
ICFD4
    LDA #CREEOF
    JMP ERROR       ;GO TO ERROR
ICFD1
    STA SVA     ;PUT INTO SAVED ACU
ICFD0
    JMP ORTN        ;GO RESTORE REGS AND RTS
;
TSTRUN
    LDA ASIBSW      ;GET AS/INT BASIC SWITCH
    BEQ TR1     ;BR IF INT
    LDX $76     ;TEST AS RUN
    BNE NOTRUN      ;BR IF NOT RUN
TR0 CLC
    RTS
TR1
    LDA $D9     ;GET INT RUN FLAG
    BMI TR0     ;BR IF RUN
NOTRUN  SEC
    RTS
ICFDB               ;NOT RUN MODE
    JSR CLOSE       ;GO CLOSE FILE
    JSR CLRSTS      ;GO CLEAR STATES
    JMP ORTN
    PAGE
;
;   NXTEXC – NEXT EXECUTE CHAR
;
NXTEXC
    JSR MVEFTA
    JSR MVBUFP      ;GO MOVE PTRS
    LDA #3
    BNE ICFD3
;
;   RBYTE – READ NEXT BYTE
;
RBYTE
    LDA #CRQRD      ;SET READ
    STA CCBREQ
    LDA #CRMNBT     ;SET NEXT BYTE
    STA CCBRQM
    JSR DOSGO       ;GO TO DOS
    LDA CCBDAT      ;GET THE DATA BYTE
    RTS
MVEFTA
    LDA EFTABA+1        ;MOVE TABLE ADR
    STA ZPGWRK+1        ;NO ZPG
    LDA EFTABA
    STA ZPGWRK
    RTS
    PAGE
;
;   DOSGO – GOTO DOS
;
DOSGO
    JSR DOSENT      ;GO TO DOS
    BCS DG1     ;BR IF ERROR
    RTS         ;DONE
;
DG1             ;*** ERROR ***
    JSR FILSRC      ;GET FILE TABLE
    BCS DG2     ;BR IF NOT FOUND
    LDA #0
    TAY
    STA (ZPGWRK), Y ;CLOSE FILE HERE
DG2
    LDA CCBSTA      ;GET STATUS OF I/O
    CMP #CREEOF     ;EOF ?
    BNE DG3     ;BR IF NOT
    LDX #0      ;SET OTHER EIF
    STX CCBDAT      ;DONE
    RTS
DG3
    JMP ERROR       ;GO DO ERROR
;
    PAGE
;
;   ERROR ROUTINE
;
ESYNTX  LDA #CREFLK+1
    BNE ERROR
ENFA    LDA #CREFLK+2
    BNE ERROR
MFERR   LDA #CREFLK+4
    BNE ERROR
ERNU1   LDA #CREFLK+3
    BNE ERROR
ENBF    LDA #CREFLK+5
;
ERROR
    STA SVA     ;SAVE MSG NUMBER
    JSR CLRSTS
    LDA ASIBSW      ;GET AS/IN BASIC SWITCH
    BEQ ERNAS       ;BR IF NOT APPLESOFT
    LDA $D8     ;GET ON ERR FLAG
    BMI ERRTN       ;BRT IF ON ERR IS GO
ERNAS
    LDX #0
    JSR EMPR        ;GO OUTPUT
    LDX SVA     ;GET SAVE MSG
    JSR EMPR        ;GO OUTPUT MSG 
    LDX #CREFLK+6
    JSR EMPR
ERRTN   JSR MVCSW       ;GO MOVE CHAR I/ SW
    LDX SVA
    LDA #03
    JMP (BREAK)
;
EMPR
    LDA EMDTB,X     ;GET ITS DISPL
    TAX         ;INTO X
EMPR1
    STX TEMP1A      ;SAVE DISPL
    LDA EMSG,X      ;GET MSG CHAR
    PHA         ;SAVE CHAR
    ORA #$80        ;SET MSB ON
    LDX TEMP1A      ;GET INDEX
    INX         ;INCREMENT IT
    PLA         ;RE-LOAD CHAR
    BPL EMPR1       ;BR IF MORE CHARS
    RTS         ;DONE
    PAGE
;
;   OPNSUP – OPEN SET UP
;
OPNSUP  
    LDA CV      ;VOLUME
    STA CCBVOL
    LDA CD      ;DRIVE
    STA CCBDRV
    LDA CS      ;SLOT
    STA CCBSLT
    LDA FN1ADR      ;FILENAME 1 ADR
    STA CCBFN1
    LDA FN1ADR+1
    STA CCBFN1+1
    LDA ZPGWRK
    STA CFTABA
    LDA ZPGWRK+1
    STA CFTABA+1
    RTS
;
;   MVFN1 – MOVE FILE NAME 1 TO FILE PTR
;
MVFN1
    LDY #29
MVFN1A  LDA FNAME1,Y
    STA (ZPGWRK),Y
    DEY
    BPL MVFN1A
    RTS
;
;   MVBUFP – MOVE BUFFER PTRS TO CCB
;
MVBUFP
    LDY #30
MVBP1   LDA (ZPGWRK),Y
    STA CCBFCB-30,Y
    INY
    CPY #38
    BNE MVBP1
    RTS
;
;   CLRSTS – CLEAR STATES
;
CLRSTS
    LDY #0
    STY ISTATE
    STY OSTATE
    RTS
    PAGE
;
;   FILSRC – SEARCH FOR FILE NAME1
;
FILSRC
    LDA #0      ;CLEAR SV AVAIL
    STA CNUM+1
;
    JSR TSINIT      ;GO INIT SEARCH
    JMP FLS1A
FLS1    JSR TSNXT       ;LOOK AT NEXT
    BEQ FLS4        ;BR IF NO NEXT
;
FLS1A   JSR TSTOPN      ;GO TEST OPEN
    BNE FLS2        ;BR IF OPEN
;
    LDA ZPGWRK      ;SAVE AVAIL ENTRY ADR
    STA CNUM
    LDA ZPGWRK+1
    STA CNUM+1
    BNE FLS1        ;GO LOOK SOME MORE
;
FLS2    LDY #29     ;FILE HAD 30 CHARS
FLS3    LDA (ZPGWRK),Y  ;GET CHAR
    CMP FNAME1,Y        ;TEST CHAR
    BNE FLS1        ;BR NOT
    DEY
    BPL FLS3        ;LOOK AT 30 CHARS
    CLC         ;FOUND
    RTS         ;DONE
;
FLS4    SEC         ;NOT FOUND
    RTS         ;DONE
    PAGE
;
;   TSINIT – INITIALIZE FOR FTAB SEARCH
;   TSNXT – GET NEXT FTAB ENTRY
;
TSINIT
    LDA FTAB        ;GET 1ST PTR ADR
    LDX FTAB+1
    BNE TSST
TSNXT
    LDY #37     ;GET LINK
    LDA (ZPGWRK),Y
    BEQ TSR     ;BR IF NO LINK
;
    TAX
    DEY
    LDA (ZPGWRK),Y
TSST
    STX ZPGWRK+1
    STA ZPGWRK
    TXA         ;SET NE CC
TSR RTS         ;RTN
;
;   TSTOPN – TST FOR OPEN FILE
;
TSTOPN
    LDY #0      ;GET 1ST CHAR OF FN
    LDA (ZPGWRK),Y
    RTS
;
;   TSTEXC – TEST CURRENT FILE FOR EXECUTE
;
TSTEXC
    LDA ESTATE      ;IF ESTATE = 0
    BEQ TXTC1       ;THEN NO EXECUTE FILE
    LDA EFTABA      ;TEST CURRENT
    CMP ZPGWRK
    BNE TXC2        ;IS NOT
    LDA EFTABA+1
    CMP ZPGWRK+1
    BEQ TXC2        ;IS
TXC1    DEX         ;IS NOT
TXC2    RTS         ;DONE
    PAGE
;
;   TSTFUC – TEST FILE USE CODE FOR PGM
;
TSTFUC
    EOR CCBFUC
    BEQ TFUCR
    AND #$7F
    BEQ TFUCR
    JSR ECLOSE      ;GO CLOSE THE SOB
    JMP ERNU1
TFUCR   RTS
    PAGE
;
;   BLDFTB – BUILD FILE TABLES
;   TABLE MAP:
;       HIMEM,SOP
;       SBUFF N     (256)
;       DBUFF N     (256)
;       FTB   N     (FCBLEN)
;       HEADER N        (38)
;
;
;       SBUFF   1
;       DBUFF   1
;       FTB 1
;       HEADER  1
;       THIS PROGRAM
;
;   HEADER MAP:
;       FILENAME (30)
;       FTB PTR  (2)
;       DBUF PTR (2)
;       SBUF PTR (2)
;       LINK     (2)
;
BLDFTB
    SEC
    LDA FTAB        ;START OF FTAB AREA
    STA ZPGWRK      ;IS 1ST FTB PTR
    LDA FTAB+1      ;HEADER
    STA ZPGWRK+1
    LDA CNFTBS      ;MOVE NO FTABS
    STA TEMP1A      ;TO TEMP
;
BFT1    LDY #0
    TYA
    STA (ZPGWRK),Y  ;1ST CHAR FN=0
    LDY #30     ;INC Y TO FCB PTR
    SEC
    LDA ZPGWRK      ;END OF PTR HEADER
    SBC #FCBLEN     ;MINUS FTAB LENGTH
    STA (ZPGWRK),Y  ;IS START OF FTB
    PHA         ;SAVE LOW ADR BYTE
    LDA ZPGWRK+1
    SBC #0
    INY
    STA (ZPGWRK),Y
    TAX
    DEX         ;FTB ADR – 256
    PLA         ;IS ADR DIR BUFF
    PHA
    INY
    STA (ZPGWRK),Y  ;SET DIR BUF PTR
    TXA
    INY
    STA (ZPGWRK),Y
    TAX
    DEX         ;DIR BUFF – 256
    PLA         ;IS SBUFF ADR
    PHA
    INY
    STA (ZPGWRK),Y
    INY
    TXA
    STA (ZPGWRK),Y
;
    DEC TEMP1A      ;DECREMENT TABLE INDEX
    BEQ BFT2        ;COUNT AND BR IF DONE
    TAX
    PLA
    SEC
    SBC #38     ;SBUFF ADR – 38
    INY
    STA (ZPGWRK),Y  ;IF ADR OF NEXT TAB
    PHA         ;WHICH GOES INTO
    TXA         ;LINK
    SBC #0
    INY
    STA (ZPGWRK),Y
    STA ZPGWRK+1        ;AND INTO ZPGWRK
    PLA         ;FOR NEXT ENTRY
    STA ZPGWRK      ;BUILD
    JMP BFT1        ;GO BUILD NEXT
;
BFT2
    PHA
    LDA #0      ;SET LAST LINK
    INY         ;TO ZERO
    STA (ZPGWRK),Y
    INY
    STA (ZPGWRK),Y
;
    LDA ASIBSW      ;IF IB THEN GO
    BEQ BFTIB
;
    PLA         ;SET APPLESOFT
    STA ASHM1+1     ;UPPER MEM LIMITS
    STA ASHM2+1
    PLA
    STA ASHM1
    STA ASHM2
    RTS
;
BFTIB
    PLA         ;SET IB
    STA IBHMEM+1        ;UPPER MEM LIMITS
    STA IBSOP+1
    PLA
    STA IBHMEM
    STA IBSOP
    RTS
    PAGE
;
;   MVISW – MOVE INPUT SWITCH
;
MVCSW
    LDA INSW+1
    CMP CINA+1
    BEQ MVOSW
    STA SVINS+1
    LDA INSW        ;SAVE CHAR INSWITCH
    STA SVINS
;
    LDA CINA        ;SET DB CHAR IN ADR
    STA INSW
    LDA CINA+1
    STA INSW+1
;
;
;   MVOSW – MOVE OUTPUT SWITCH
;
MVOSW
    LDA OUTSW+1
    CMP COUTA+1
    BEQ MVSRTN
    STA SVOUTS+1
    LDA OUTSW       ;SAVE CHAR OUT SWITCH
    STA SVOUTS
;
    LDA COUTA       ;SET DB CHAR OUT ADR
    STA OUTSW
    LDA COUTA+1
    STA OUTSW+1
MVSRTN
    RTS
    PAGE
;
;   COMMAND NAME TABLE
;
EC1
CMDNTB
    DB01    "INIT"
    DB01    "LOAD"
    DB01    "SAVE"
    DB01    "RUN"
    DB01    "CHAIN"
    DB01    "DELETE"
    DB01    "LOCK"
    DB01    "UNLOCK"
    DB01    "CLOSE"
    DB01    "READ"
    DB01    "EXEC"
    DB01    "WRITE"
    DB01    "POSITION"
    DB01    "OPEN"
    DB01    "APPEND"
    DB01    "RENAME"
    DB01    "CATALOG"
    DB01    "MON"
    DB01    "NOMON"
    DB01    "PR#"
    DB01    "IN#"
    DB01    "MAXFILES"
    DB01    "FP"
    DB01    "INT"
    DB01    "BSAVE"
    DB01    "BLOAD"
    DB01    "BRUN"
    DB01    "VERIFY"
    DB  0
    PAGE
;
;   COMMAND SYNTAX OP EQUATES FOR SYNTAX BYTE ONE
;
NPB EQU $80     ;NO PARMS OK, COMMAND GOES TO BASIC
NPE EQU $40     ;NO PARMS OK, COMMAND TO EXECUTION RTN
FN1 EQU $20     ;FILE NAME1 REGD
FN2 EQU $10     ;FILE NAME2 REGD
NUM1    EQU $08     ;NUMERIC 0-7 REGD
NUM2    EQU $04     ;NUMERIC 1-10 REGD
;
;   COMMAND SYNTAX OP EQUATES FOR SYNTAX BYTE TWO
;
V   EQU $40     ;VOLUME ALLOWED
D   EQU $20     ;DRIVE ALLOWED
S   EQU $10     ;SLOT ALLOWED
L   EQU $08     ;LENGTH ALLOWED
R   EQU $04     ;RECORD NUMBER ALLOWED
B   EQU $02     ;BYTE NUMBER ALLOWED
A   EQU $01     ;ADDRESS
CIO EQU $80     ;C,I, OR O ALLOWED
;
;   COMMAND SYNTAX TABLE
;   EACH COMMAND HAS TWO BYTE ENTRY
;
;
CMDSTB
    DB  FN1,V+D+S   ;INIT
    DB  NPB+FN1,V+D+S   ;LOAD
    DB  NPB+FN1,V+D+S   ;SAVE
    DB  NPB+FN1,V+D+S   ;RUN
    DB  FN1,V+D+S   ;CHAIN
    DB  FN1,V+D+S   ;DELETE
    DB  FN1,V+D+S   ;LOCK
    DB  FN1,V+D+S   ;UNLOCK
    DB  NPE+FN1,0   ;CLOSE
    DB  FN1,B+R     ;READ
    DB  FN1,R+V+D+S ;EXEC
    DB  FN1,B+R     ;WRITE
    DB  FN1,R       ;POSITION
    DB  FN1,L+V+D+S ;OPEN
    DB  FN1,L+V+D+S ;APPEND
    DB  FN1+FN2,V+D+S   ;RENAME
    DB  NPE,V+D+S   ;CATALOG
    DB  NPE,CIO     ;MONITOR
    DB  NPE,CIO     ;NO MONITOR
    DB  NUM1,0      ;PR#
    DB  NUM1,0      ;IN#
    DB  NUM2,0      ;MAXFILES
    DB  NPE,V+D+S   ;APPLESOFT
    DB  NPE,0       ;INT
    DB  FN1,V+D+S+A+L   ;BSAVE
    DB  FN1,V+D+S+A ;BLOAD
    DB  FN1,V+D+S+A ;BRUN
    DB  FN1,V+D+S   ;VERIFY
    PAGE
;
;   OPTAB – OPTIONAL PARMS SYNTAX TABLES
;
OPTAB1
    DB11    "VDSLRBACIO"
OPT1L   EQU *-OPTAB1
OPTAB2
    DB  V,D,S,L,R,B,A,CIO+MC,CIO+MI,CIO+MO
OPTAB3
    DB  @@0,@@254   ;VOL RANGE
    DB  @@1,@@2     ;DRIVE RANGE
    DB  @@1,@@7     ;SLOT RANGE
    DB  @@1,@@32767 ;LENGTH RANGE
    DB  @@0,@@32767 ;REC NO RANGE
    DB  @@0,@@32767 ;REC BYTE NO RANGE
    DB  @@0,@@$C000 ;ADDRESS RANGE
    PAGE
;
;   ERROR MESSAGE TABLES
;
EMSG
    DB  $0D,$07
    DB01    "***DISK: "
EM1 EQU *-EMSG
EM2 EQU *-EMSG
EM3 EQU *-EMSG
    DB01    "SYS"
EM4 EQU *-EMSG
    DB01    "WRITE PROTECT"
EM5 EQU *-EMSG
    DB01    "END OF DATA"
EM6 EQU *-EMSG
    DB01    "FILE NOT FOUND"
EM7 EQU *-EMSG
    DB01    "VOLUME MISMATCH"
EM8 EQU *-EMSG
    DB01    "DISK I/O"
EM9 EQU *-EMSG
    DB01    "DISK FULL"
EM10    EQU *EMSG
    DB01    "FILE LOCKED"
EM11    EQU *EMSG
    DB01    "CMD SYNTAX"
EM12    EQU *-EMSG
    DB01    "NO FILE BUFFS AVAIL"
EM13    EQU *-EMSG
    DB01    "NOT BASIC PROGRAM"
EM14    EQU *-EMSG
    DB01    "PROGRAM TOO LARGE"
EM15    EQU *-EMSG
    DB01    "NOT BINARY FILE"
;
EML EQU *-EMSG
    DB  " ERROR"
    DB  $8D
EMDTB
    DB  0,EM1,EM2,EM3,EM4
    DB  EM5,EM6,EM7,EM8,EM9
    DB  EM10,EM11,EM12,EM13,EM14
    DB  EM15
    PAGE
;
;   MISC BUT REQD CELLS
;
CFTABA  DB  @0      ;CURRENT FILE TABLE POINTER
ISTATE  DB  0       ;INPUT STATE
OSTATE  DB  0       ;OUTPUT STATE
SVOUTS  DB  @0      ;SAVED OUT SWITCH
SVINS   DB  @0      ;SAVED IN SWITCH
CNFTBS  DB  0       ;CURRENT NO FILE TABLES
DFNFTB  DB  3       ;DEFAULT NO FILE TABLES
SVSTK   DB  0       ;SAVED STACK PTR
SVX DB  0       ;DSAVED X REG
SVY DB  0       ;SAVED XREG
LBUFD   DB  0       ;SAVED ACU
MONMOD  DB  0       ;LINE BUFF DISPL
MC  EQU $40     ;MONITOR MODE BITS
MI  EQU $20     ;MONITOR CMDS
MO  EQU $10     ;MONITOR OUTPUT
CMDNO   DB  $FF     ;COMMAND NO
SVBL    DB  0,0
 
SVCMD   DB  0
TEMP1A  DB  0
TEMP2A  DB  0
INOPTS  DB  0       ;INPUT OPTIONS
CUROPT              ;CURRENT OPTIONS
CV  DB  @@0     ;VOLUME
CD  DB  @@0     ;DRIVE
CS  DB  @@0     ;SLOT
CL  DB  @@1     ;RECORD LENGTH
CR  DB  @@0     ;RECORD NUMBER
CB  DB  @@0     ;RECORD BYTE
CA  DB  @@0     ;ADDRESS
IMBITS  DB  0
FNAME1  RMB 30      ;FILENAME 1
FNAME2  RMB 30      ;FILENAME 2
DFNFTS  DB  3       ;DEFAULT FILE TABLES = 3
CCHAR   DB  $84     ;CONTROL CHAR
ESTATE  DB  0       ;EXECUTE STATE
EFTABA  DB  0,0     ;EXECUTE FILE TABLE POINTER
ASIBSW  DB  0       ;APPLESOFT, IB SWITCH
FASB    DB11    "APPLESOFT"
FASBL   EQU *-FASB
    PAGE
;
;   DOS ADR TABLES (RELOCATED)
;
SAT2
AIOB    DB  @@IOB       ;5-ADR IOB
AVTOC   DB  @@VTOC      ;6-ADR VTOC
AVOLDR  DB  @@VOLDIR        ;7-ADR VOLDIR
AEND    DB  @@EDOS      ;FEND OF DOS
;
CMDVT   DB  @@GOODIO-1  ;0-NULL
    DB  @@FOPEN-1   ;1-OPEN FILE
    DB  @@FCLOSE-1  ;2-CLOSE FILE
    DB  @@FREAD-1   ;3-READ FILE
    DB  @@FWRITE-1  ;4-WRITE DATA
    DB  @@FDEL-1        ;5-DELETE FILE
    DB  @@FDIR-1        ;6-READ DIRECTORY
    DB  @@FLOCK-1   ;7-LOCK A FILE
    DB  @@FUNLCK-1  ;8-UNLOCK A FILE
    DB  @@FRNME-1   ;9-RENAME
    DB  @@FPOSTN-1  ;10-POSITION A FILE
    DB  @@FFMT-1        ;FORMAT
    DB  @@FVAR-1        ;VARIFY
    DB  @@GOODIO-1  ;11-SPARE
;
RVT
    DB  @@GOODIO-1
    DB  @@RNXBYT-1  ;1-RD NEXT BYTE
    DB  @@RNXBLK-1  ;1-RD NEXT BLOCK
    DB  @@RSPBYT-1  ;2-RD SPECIFIC BYTE
    DB  @@RSPBLK-1  ;3-RD SPECIFIC BLOCK
    DB  @@GOODIO-1  ;4-SPARE
;
WVT
    DB  @@GOODIO-1
    DB  @@WNXBYT-1  ;1-WR NEXT BYTE
    DB  @@WNXBLK-1  ;WR NEXT BLOCK
    DB  @@WSPBYT-1  ;2-WR SPECIFIC BYTE
    DB  @@WSPBLK-1  ;3-WR SPECIFIC BLOCK
    DB  @@GOODIO-1  ;4- SPARE
EAT2
    PAGE
;
;   DOSENT – DOS EXTERNAL ENTRY POINT
;       EXIT PARM
;               CARRY CLEAR = OPERATION
;               CARRY SET = ERROR
;
SC2
DOSENT
    TSX
    STX ENTSTK
    JSR CLCFCB      ;GO CALCULATE FCB
    LDA CCBREG      ;GET REQUEST
    CMP #CRGMAX     ;TTEST REQ RANGE
    BCS ERR2        ;BR OUT OF RANGE
    ASLA            ;REQ CODE *2
    TAX
    LDA CMDVT+1,X   ;PUSH ADR ONTO STACK
    PHA
    LDA CMDVT,X
    PHA
DENRTS  RTS
ERR2    JMP ERROR2
    PAGE
;
;   FOPEN – OPEN A FILE
;
FOPEN
    JSR DOPEN
    JMP GOODIO
;
DOPEN
;
    JSR DCBSUP
;
;
    LDA #1
    STA DCBSDL+1
    LDX CCBRLN+1        ;MOVE RECORD LENGTH
    LDA CCBRLN
    BNE F02
    CPX #0
    BNE F02
    INX         ;SET RL=256
F02 STA DCBRCL
    STX DCBRCL+1
;
    JSR FNDFIL      ;GO FIND FILE
    BCC F03     ;BR IF FOUND
;               ;CREATE FILE
    LDA #0
    STA VDFILE+34,X
    LDA #1
    STA VDFILE+33,X
    STX TEMP1       ;SAVE VDIR INDEX
    JSR GETSEC      ;GO ALLOCATE SECTOR
    LDX TEMP1
    STA VDFILE+1,X  ;PUT SECTOR INTO VDIR
    STA DCBFDS      ;PUT SECTOR AS 1ST FILE DIR
    STA DCBCDS      ;PUT SECTOR AS CURRENT FILE DIR
;   
    LDA DCBATK      ;GET ALLOCATED TRACK
    STA VDFILE,X        ;PUT INTO VDIR
    STA DCBFDT      ;AND AS 1ST FILE DIR
    STA DCBCDT      ;AND AS CURRENT FILE DIR
;
    LDA CCBFUC      ;SET USE CODE
    STA VDFILE+2,X  ;INTO DIRECTORY
;
    JSR WRVDIR      ;GO WRITE VOL DIRECTORY
;
    JSR MVFCBD      ;MOVE FILE DIR ADR TO ZP
    JSR CLRSEC      ;GO CLEAR IT
    JSR WRFGO       ;GO WRITE FILE DIRECTORY DONE CREATION
;
    LDX TEMP1       ;RE-GET INDEX
    LDA #CREFNF
    STA CCBSTA
;
F03
    LDA VDFILE,X        ;MOVE FILE DIR TRACK
    STA DCBFDT
    LDA VDFILE+1,X  ;MOVE FILE DIR SECTOR
    STA DCBFDS
    LDA VDFILE+2,X  ;70VE FILE USE CODE
    STA CCBFUC
    STA DCBFUC
    LDA VDFILE+33,X
    STA DCBNSA
    LDA VDFILE+34,X
    STA DCBNSA+1
    STX DCBVDI      ;SAVE DIR INDEX
;
    LDA #255        ;INDICATE NO SECTOR
    STA DCBCMS      ;IN MEMORY
    STA DCBCMS+1
    LDA VTDMS       ;MOVE MAX FD SECTS
    STA DCBDMS      ;TO DCB
    CLC
    JMP RDFDIR      ;READ 1ST DIRECTORY RECORD
;
;
;
;
DCBSUP
    LDA #0
    TAX
F01 STA FCBDCB,X        ;CLEAR DCB
    INX
    CPX #DCBLEN
    BNE F01
;
    LDA CCBVOL      ;MOVE VOL
    EOR #$FF        ;INVERT VOL BITS
    STA DCBVOL
    LDA CCBDRV      ;MOVE DRIVE
    STA DCBDRV
    LDA CCBSLT      ;GET USER SPEC SLOT
    ASLA            ;SLOT*16
    ASLA
    ASLA
    ASLA
    TAX
F01A    
    STX DCBSLT
    LDA #17
    STA DCBVTN
    RTS
 
    PAGE
;
;   FCLOSE – CLOSE A FILE
;
FCLOSE
    JSR WRSECT      ;WRITE OPEN SECTOR
    JSR WRFDIR      ;GO WRITE FILE DIRECTORY
    JSR FRETRK      ;FREE UNUSED SECTORS
    LDA #IBCWTS
    AND DCBWRF
    BEQ FC2
;
    JSR RDVTOC      ;READ VTOC
    LDA #0
    CLC
FC1
    JSR RDVDIR      ;READ VDIR
    SEC
    DEC DCBVDR
    BNE FC1     ;BR IF NOT
    LDX DCBVDI      ;GET FILES INDEX
    LDA DCBNSA      ;MOVE NO SECTIONS ALLOCATED
    STA VDFILE+33,X
    LDA DCBNSA+1
    STA VDFILE+34,X
    JSR WRVDIR      ;WRITE VOL DIR REC
;
;
FC2
    JMP GOODIO      ;DONE
    PAGE
;
;   FRNME – RENAME A FILE
;
FRNME
    JSR DOPEN       ;GO OPEN FILE
    LDA DCBFUC      ;GET USE CODE
    BMI ER10        ;BR IF LOCKED
    LDA CCBFN2      ;MOVE NEW FN
    STA ZPGFCB      ;PTR TO ZPG
    LDA CCBFN2+1
    STA ZPGFCB+1
    LDX TEMP1       ;GET VDIR INDEX
    JSR MVFN        ;GO MOVE FILE NAME
    JSR WRVDIR      ;GO WRITE FILE VDIR
    JMP GOODIO      ;DONE RENAME
    PAGE
;
;   FREAD – READ A FILE
;
FREAD
;
    LDA CCBRQM      ;GET REQ MOD
    CMP #CRMMAX     ;TEST LIMIT
    BCS ERR3A
;
    ASLA            ;CODE*2
    TAX
    LDA RVT+1,X     ;GET READ ROUTINE
    PHA         ;VECTOR ADR
    LDA RVT,X
    PHA         ;AND
    RTS         ;GO TO IT
;
ERR3A   JMP ERROR3
ER10    JMP ERRR10
;
;   FWRITE – WRITE A FILE
;
FWRITE
    LDA DCBFUC      ;IS FILE LOCKED
    BMI ER10        ;BR IF LOCKED
    LDA CCBRQM      ;GET REQ MOD
    CMP #CRMMAX     ;IN RANGE
    BCS ERR3A       ;BR IF NOT IN RANGE
;
    ASLA
    TAX
    LDA WVT+1,X     ;GET ROUTINE ADR
    PHA
    LDA WVT,X
    PHA
    RTS         ;AND GO TO IT
    PAGE
;
;   RSPBYT – READ A SPECIFIC BYTE
;
RSPBYT
    JSR LOCSEC      ;GO GET REQD REL SECTOR
;
;   RNXBYT – READ NEXT BYTE
;
RNXBYT  JSR GETBYT      ;GO GET BYTE
    STA CCBDAT      ;PUT IN CCB
    JMP GOODIO      ;DONE
;
;   RSPBLK – READ SPECIFIC BLOCK
;
RSPBLK  JSR LOCSEC      ;GO LOCATE REL SECTOR
;
;   RNXBLK – READ NEXT BLOCK
;
RNXBLK
    JSR DTBLN       ;GO DECR LEN (NOT RTN IF=0)
    JSR GETBYT      ;GO GET BYTE
    PHA
    JSR MIBDA       ;GO MOVE BLOCK ADR AND INCR
    LDY #0
    PLA
    STA (ZPGFCB),Y  ;SET DATA BYTE
    JMP RNXBLK      ;GO FOR NEXT BYTE
;
;   GETBYT – GET A DATA BYTE
;
GETBYT
    JSR LOCNXB      ;LOCATE NEXT BYTE
    BCS EOFIN       ;BR IF EOF
    LDA (ZPGFCB),Y  ;BR IF EOF
    PHA         ;SAVE IT
    JSR INCRRB      ;INCR REC BYTE
    JSR INCSCB      ;INCR SAVED BYTE
    PLA         ;GET SAVED BYTE
    RTS         ;RETURN
;
EOFIN   JMP ERROR5      ;GO TO EOF RTN
    PAGE
;
;   WSPBYT – WRITE SPECIFIC BYTE
;
WSPBYT
    JSR LOCSEC      ;GO LOCATE SECTOR
;
;   WNXBYT – WRITE NEXT BYTE
;
WNXBYT
    LDA CCBDAT      ;GET THE BYTE
    JSR PUTBYT      ;GO WRITE BYTE
    JMP GOODIO      ;DONE
;
;   WSPBLK – WRITE NEXT BLOCK
;
WSPBLK
 
    JSR LOCSEC      ;GO LOCATE SECTOR
;
;   WNXBLK – WRITE BLOCK
;
WNXBLK
    JSR MIBDA       ;GO MOVE ADR TO ZPG AND DEC
    LDY #0
    LDA (ZPGFCB),Y  ;GET DATA BYTE
    JSR PUTBYT      ;GO PUT IT
    JSR DTBLN       ;GO DEC BLK LEN (NOT RTN IF = 0)
    JMP WNXBLK
;
;   PUTBYT – PUT OUT ONE BYTE
;
PUTBYT
    PHA         ;SAVE DATA BYTE
    JSR LOCNXB      ;GO LOCATE NEXT BYTE
;
PB0 PLA         ;GO SAVED BYTE
    STA (ZPGFCB),Y  ;PUT THE BYTE
    LDA #$40        ;SET WRITE SECTOR REQD
    ORA DCBWRF
    STA     DCBWRF
;
    JSR INCRRB      ;INCR REL REC BYTE
    JMP INCSCB      ;INCR SECTOR BYTE
    PAGE
;
;   FLOCK – LOCK A FILE
;
FUNLOCK LDA #$80        ;REMEMBER LOCK
    STA TEMP3
    BNE LCKGO
;
;   FUNLCK – UNLOCK A FILE
;
FUNLCK  LDA #00     ;REMEMBER UNLOCK
    STA TEMP3
;
LCKGO
;
    JSR DOPEN       ;GO OPEN FILE
    LDX TEMP1
    LDA VDFILE+2,X  ;GET FILE USE CODE
    AND #$7F        ;TURN OFF LOCK
    ORA TEMP3
    STA VDFILE+2,X
    JSR WRVDIR
    JMP GOODIO
;
;   FPOSTN – POSITION A FILE
FPOSTN  JSR LOCSEC      ;GO POSITION
    JMP GOODIO      ;DONE
;
;
;   FVAR – VARIFY A FILE
;
FVAR
    JSR DOPEN       ;OPEN FILE
VAR1    JSR LOCNXB      ;READ A SECTOR
    BCS VAR2        ;BR IF EOF
    INC DCBCRS      ;INCREMENT SECTOR
    BNE VAR1
    INC DCBCRS+1
    JMP VAR1        ;READ THIS ONE
VAR2    JMP GOODIO      ;DONE   
    PAGE
;
;   FDEL – DELETE A FILE
;
FDEL
    JSR DOPEN       ;GO OPEN FILE
;
FD2 LDX TEMP1       ;SAVED INDEX
    LDA VDFILE+2,X  ;IS FILE LOCKED
    BPL FD3     ;BR NOT LOCKED
    JMP ERRR10
;
FD3
    LDX TEMP1       ;GET SAVED INDEX
    LDA VDFILE,X        ;GET DIR TRACK
    STA DCBFDT      ;SET AS 1ST FD TRACK
    STA VDFILE+32,X ;SAVE IN LC OF FN
    LDA #$FF        ;DELETED FILE MARKER
    STA VDFILE,X        ;CLEAR ENTRY
    LDY VDFILE+1,X  ;GET DIR SECTOR
    STY DCBFDS      ;SET AS 1ST FD SEC
    JSR WRVDIR      ;GO WRITE VOLUME DIR
    CLC
FD4 JSR RDFDIR      ;GET 1ST FILE DIR SECTOR
    BCS FD7     ;BR IF NO MORE
    JSR MVFCBD      ;MOVE DIR TO ZPG
    LDY #FDENT      ;POINT Y TO 1ST SEC ENT
FD5 STY TEMP1       ;SAVE Y
    LDA (ZPGFCB),Y  ;GET REACK
    BMI FD6     ;BR IF DONE
    BEQ FD6     ;BR IF END OF FILE
    PHA         ;SAVE TRK
    INY
    LDA (ZPGFCB),Y  ;GET SECTOR
    TAY         ;TO Y
    PLA         ;GET TRK
    JSR FDSUB       ;GO FREE SECTOR
FD6 LDY TEMP1       ;GET DIR INDEX
    INY         ;INCR TO NEXT ENTRY
    INY
    BNE FD5     ;BR NOT DONE THIS DIR
    LDA DCBCDT      ;GET THIS DIR TRK
    LDY DCBCDS      ;AND SECTOR
    JSR FDSUB       ;AND GO FREE IT
    SEC         ;GO
    BCS FD4     ;READ NEXT DIR
FD7
    JSR WRVTOC
    JMP GOODIO
;
FDSUB
    SEC         ;SET FOR RE USE OF SEC
    JSR FRESEC      ;GO FREE SECTOR
    LDA #0      ;CLEAR DCB BIT MAP
    LDX #3
FDS1    STA DCBALS,X
    DEX
    BPL FDS1
    RTS
    PAGE
;
;   RDIR – PRINT DIRECTORY
;
RDIR
    JSR DCBSUP
    LDA #$FF
    STA DCBVOL
    JSR RDVTOC
    LDA #22     ;SET 21 LINES
    STA TEMP2
    JSR PRCR        ;GO PRINT
    JSR PRCR        ;PRINT ANOTHER CHAR
    LDX #VML        ;VOLUME MSG LENGTH
RDO LDA VOLMES,X        ;GET MSG CHAR
    JSR PRINT       ;PRINT IT
    DEX         ;DECREMENT COUNT
    BPL RDO     ;BR IF MORE
;
    STX CNUM+1  
    LDA IBSMOD      ;MOVE VOL NO FOR
    STA CNUM        ;CONVERSION
    JSR PRNUM       ;GO PRINT VOL NO
;
    JSR PRCR        ;PRINT CR
    JSR PRCR        ;AND AGAIN
;
    CLC         ;FIRST RECORD
;
RD1 JSR RDVDIR      ;GO READ REC
    BCS RD5
    LDX #0      ;SET INDEX=0
RD2 STX TEMP1       ;SAVE INDEX
    LDA VDFILE,X        ;GET TRACK
    BEQ RD5     ;BR IF END OF DIR
    BMI RD4     ;BR IF DELETED
;
    LDY #$A0        ;BLANK
    LDA VDFILE+2,X  ;GET TYPE
    BPL RD2A        ;BR IF NOT LOCKED
    LDY #’*+$80       ;AST
RD2A    TYA         ;ACU = AST OR BLANK
    JSR PRINT       ;PRINT ACU
;
    LDA VDFILE+2,X  ;GET TYPE
    AND #$07        ;MASK OUT MISC
    LDY #3      ;SET INDEX = 3
RD2B    LSRA            ;SHIFT OUT LSB
    BCS RD2C        ;BR IF TYPE BIT OUT
    DEY         ;DEC INDEX
    BNE RD2B        ;BR IF NOT ACC BITS
RD2C
    LDA FTTAB,Y     ;GET TYPE CODE
    JSR PRINT       ;PRINT IT
    LDA #$A0        ;BLANK
    JSR PRINT       ;PRINT
;
    LDA VDFILE+33,X ;MOVE FILE LENGTH
    STA CNUM        ;TO CNUM
    LDA VDFILE+34,X
    STA CNUM+1
    JSR PRNUM       ;GO PRINT NUMBER
    LDA #$A0        ;BLANK
    JSR PRINT       ;PRINT
;
    INX
    INX
    INX
    LDY #29
RD3 LDA VDFILE,X        ;GET CHAR
    JSR PRINT       ;PRINT CHAR
    INX
    DEY
    BPL RD3
RD3A
    JSR PRCR        ;GO PRINT CR
RD4 JSR VDINC       ;INCR INDEX
    BCC RD2     ;BR IF MORE IN DIR
    BCS RD1     ;GO READ NEXT DIR SECT
;
RD5 JMP GOODIO      ;DONE
;
PRCR
    LDA #$8D        ;CR
    JSR PRINT       ;PRINTED
    DEC TEMP2       ;DEC LINE COUNTER
    BNE PRCR1       ;BR IF NOT ZERO
    JSR GETKEY      ;WAIT FOR INPUT
    LDA #21     ;RESET LINE COUNTER
    STA TEMP2
PRCR1   RTS         ;DONE
    PAGE
PRNUM
    LDY #2      ;3 DIGITS
PRN1    LDA #0      ;INIT DIGIT TO ZERO
    PHA         ;SAVE IT
;
PRN2    LDA CNUM        ;GET NUMBER
    CMP CVTAB,Y     ;IF NUM < CVTAB ENTRY
    BCC PRN3        ;THEN DONE THIS DIGIT
;
    SBC CVTAB,Y     ;SUBTRACT TABLE ENTRY
    STA CNUM        ;FROM NUM
    LDA CNUM+1
    SBC #0
    STA CNUM+1
    PLA         ;INCREMENT DIGIT
    ADC #0
    PHA
    JMP PRN2        ;TRY AGAIN
;
PRN3
    PLA         ;GET DIGIT
    ORA #$B0        ;ADD ASCII
    JSR PRINT       ;PRINT IT
    DEY         ;DECREMENT DIGIT COUNT
    BPL PRN1        ;BR IF MORE DIGIT
;
    RTS         ;DONE
    PAGE
;
;   CLCFCB – GET FCB VIA INDEX AND MOVE IT
;
CLCFCB
;
    JSR MVFCBP      ;MOVE FCB PTR TO ZPG
    LDY #0
    STY CCBSTA
CF3 LDA (ZPGFCB),Y  ;MOVE FCB TO
    STA FCB,Y       ;FCB WORK AREA
    INY
    CPY #FCBLEN
    BNE CF3
;
    CLC         ;DONE
    RTS
;
;   RTNFCB – MOVE FCB FROM WORK AREA TO FCB
;
RTNFCB
    JSR MVFCBP      ;MOVE FCB ADR TO ZPG
;
    LDY #0
RF1 LDA FCB,Y
    STA (ZPGFCB),Y
    INY
    CPY #FCBLEN
    BNE RF1
    RTS
    PAGE
;
;   FFMT – EXECUTE FORMAT REQUEST
;
FFMT
    JSR DCBSUP      ;SET UP DCB
    LDA #IBFMT
    JSR DCBIO2
    LDA DCBVOL      ;SET VOL NO
    EOR #$FF
    STA VVOLNO
    LDA #17
    STA VALCA1      ;ALOCATE BYTE 1
    LDA #1
    STA VALCA2      ;ADD BYTE 2
;
    LDX #VSECAL-VTOC
    LDA #0
NT1 STA VTOC,X      ;CLEAR SECTOR AREA
    INX
    BNE NT1
;
    LDX #3*4        ;START AT TRACK 3
NT2 CPX #35*4       ;END AT TRACK 35
    BEQ NT4
    LDY #3      ;4 BYTES OF INFO
NT3 LDA ALC10S,Y        ;10 SECTORS ALLOCATE
    STA VSECAL,X
    INX
    DEY
    BPL NT3
    CPX #17*4       ;AT TRACK 17
    BNE NT2     ;BR IF NOT
    LDX #18*4       ;SKIP TO 18
    BNE NT2
;
NT4 JSR WRVTOC      ;WRITE NEW VTOC
;
    LDX #0
    TXA
NT5 STA VOLDIR,X        ;CLEAR VOLDIR
    INX
    BNE NT5
;
    JSR MVVDBA      ;MOVE BUF PTRS
;
    LDA #17     ;TRACK 17
    LDY VNOSEC
    DEY
    DEY
    STA IBTRK       ;INTO IOB
NT6 STA VDLTRK      ;INTO LINK
NT7 STY VDLSEC
    INY
    STY IBSECT
    LDA #IBCWTS
    JSR DCBIO2
    LDY VDLSEC
    DEY         ;DECREMENT SECTOR
    BMI NT8     ;BR LAST WRITTEN
    BNE NT7     ;BR NOT LAST
    TYA         ;LAST, SET LINK TRK=0
    BEQ NT6
;
NT8
    JSR DLDSUP      ;GO SET UP FOR DOSLDR
    JSR WBOOT       ;GO WRITE THE BOOT
    JMP GOODIO      ;DONE
    PAGE
;
;   DLDSUP – SET UP FOR DOSLDR
;
DLDSUP
    LDA CCBBSA
    STA IBBUFP+1        ;START ADR
    LDA #0
    STA IBBUFP
    LDA DCBVOL      ;VOL
    EOR #$FF
    STA IBVOL
    RTS
    PAGE
;
;   MVFCBX – MOVE FCB ADRS TO ZPGFCB
;
MVFCBP  LDX #0      ;MOVE FCB ADR
    BEQ MVF1
MVFCBD  LDX #2      ;MOVE FCB DIR BUFF
    BNE MVF1        
MVFCBS  LDX #4      ;MOVE FCB SECTOR BUFF
;
MVF1
    LDA CFCBAD,X        ;DO THE MOVE
    STA ZPGFCB
    LDA CFCBAD+1,X
    STA ZPGFCB+1
    RTS
;
;   CLRSEC – CLEAR SECTOR
;
CLSEC
    LDA #0
    TAY
CS1 STA (ZPGFCB),Y
    INY
    BNE CS1
    RTS
    PAGE
;
;   WRSECT – WRITE CURRENT SECTOR IF REQD
;
WRSECT
    BIT DCBWRF      ;GET WRITE REQD FLAG
    BVS WRSGO       ;BR IF WRITE SECTOR REQD
    RTS         ;RTS
;
WRSGO
    JSR MVSBA       ;GO MOVE SECT BUFF ADR
;
    LDA #IBCWTS     ;GET COMMAND
    JSR DCBIO       ;GO FILL IN IOB AND DO IO
;
    LDA #$BF        ;SET WRITE SECTOR REQD BIT OFF
    AND DCBWRF
    STA DCBWRF
    RTS         ;DONE
    PAGE
;
;   WRFDIR – WRITE FILE DIRECTORY IF REQD
;
WRFDIR
    LDA DCBWRF      ;GET WRITE REQD FLAG
    BMI WRFDGO      ;BR IF WRITE DIR REQD
    RTS         ;DONE IF NOT
;
WRFDGO
    JSR MVFDBA
;
    LDA #IBCWTS     ;GET WRITE CMD
    JSR DCBIO       ;GO FILL IN IOB AND DO I/O
;
    LDA #$7F        ;TURN WRITE DIR REQD BIT OFF
    AND DCBWRF
    STA DCBWRF
    RTS         ;DONE
;
;   MVFDBA – MOVE FILE DIRECTORY BUFF ASDR TO IOD
;
MVFDBA
    LDA CFCBDR      ;MOVE ADR
    STA IBBUFP
    LDA CFCBDR+1
    STA IBBUFP+1
    LDX DCBCDT      ;GET TRACK
    LDY DCBCDS      ;GET SECTOR
    RTS
    PAGE
;
;   RDFDIR – READ FILE DIRECTORY
;
RDFDIR
    PHP         ;SAVE STATUS
    JSR WRFDIR      ;GO WRITE CURRENT DIR IF REQD
    JSR MVFDBA      ;GO MOVE DBUFF ADR TO ZPG
    JSR MVFCBD      ;MOVE DBUFF ADR TO ZPG
    PLP         ;GET SAVED STATUS
    BCS RFDNXT      ;BR IF RD NEXT
;
    LDX DCBFDT      ;TRACK
    LDY DCBFDS      ;SECTOR
    JMP RFDIO1      ;GO READ
;
RFDNXT
    LDY #FDLTRK     ;GET LINK TRACK
    LDA (ZPGFCB),Y
    BEQ RFDNL       ;NR NO LINK
    TAX         ;PUT TRACK INTO X
    INY
    LDA (ZPGFCB),Y  ;SET LINK SECTOR
    TAY         ;PUT SECTOR INTO Y
    JMP RFDIO1      ;GO DO I/O
;
RFDNL
    LDA CCBREG      ;THIS A WRITE
    CMP #CRQWR
    BEQ RFDNL1      ;BR IF WRITE
    SEC         ;SET EOF
    RTS         ;RETURN
;
RFDNL1
    JSR GETSEC      ;GET A SECTOR
    LDY #FDLSEC
    STA (ZPGFCB),Y  ;PUT IN LINK
    PHA         ;SAVE SECTOR
    DEY
    LDA DCBATK      ;GET TRACK
    STA (ZPGFCB),Y  ;PUT IN LINK
    PHA         ;SAVE TRACK
    JSR WRFDGO      ;GO WRITE OLD DIR DEC
;
    JSR CLRSEC      ;CLEAN OUT DIR
    LDY #FDFRS      ;SET NEW DIR SEC 1ST REL
    LDA DCBDNF      ;FILE SECTOR
    STA (ZPGFCB),Y
    INY
    LDA DCBDNF+1
    STA (ZPGFCB),Y
;
    PLA         ;GET SAVED TRACK
    TAX         ;INTO X
    PLA         ;GET SAVED SECTOR
    TAY         ;INTO Y
    LDA #IBCWTS     ;SET WRITE CMD
    BNE RFDIO2      ;GO DO I/O
;
RFDIO1  LDA #IBCRTS     ;SET READ CMD
RFDIO2  STX DCBCDT      ;SET CURR TRACK
    STY DCBCDS      ;SET CURR SECTOR
    JSR DCBIO       ;GO I/O
;
RDFDC   LDY #FDFRS      ;GET POINTER TO FIRST RE SECTOR
    LDA (ZPGFCB),Y  ;GET FRS
    STA DCBDFS      ;SET INTO DCB
    CLC
    ADC DCBDMS      ;ADD MAX SECTORS
    STA     DCBDNF      ;PUT INTO DCB
;
    INY         ;DO SAME FOR HI BYTE
    LDA (ZPGFCB),Y
    STA DCBDFS+1
    ADC DCBDMS+1
    STA DCBDNF+1
;
    CLC
    RTS         ;DONE
    PAGE
;
;   RDSECT – READ A SECTOR
;
RDSECT
    JSR MVSBA       ;GO MOVE SECTOR BUFFER ADR
;
    LDA #IBCRTS
    JMP DCBIO       ;GO DO I/O
;
;   MVSBA – MOVE SECTOR BUFFER ADR FOR I/O
;
MVSBA
    LDY CFCBSB      ;GET SECTOR BUFF ADR
    LDA CFCBSB+1    
MSB1    STY IBBUFP      ;SET IOB SECTOR
    STA IBBUFP+1        ;BUFF PTR
    LDX DCBTRK      ;GET TRACK
    LDY DCBSEC      ;GET SECTOR
    RTS         ;RTN
    PAGE
;
;   RDVTOC – READ VTOC
;   WRVTOC – WRITE VTOC
;
RDVTOC
    LDA #IBCRTS     ;READ
    BNE VTIO
WRVTOC
    LDA #IBCWTS     ;WRITE
;
VTIO    LDY AVTOC       ;MOVE BUFF ADR
    STY IBBUFP
    LDY AVTOC+1
    STY IBBUFP+1
;
    LDX DCBVTN      ;GET TRACK
    LDY #0
    JMP DCBIO       ;GO DO I/O
    PAGE
;
;   RDVIR – READ VOLUME DIRECTOR
;
RCVIR
    PHP         ;SAVES STATUS
    JSR MVVDBA
;
    PLP         ;GET STATUS
    BCS RVDA        ;BR IF R0 NEXT
;
RVDC    LDY VDIRSC      ;GET LINK SECTOR
    LDX VDIRTK      ;GET FIRST TRK
    BNE RVDGO       ;GO READ
;
RVDA
    LDX VDLTRK      ;GET SECTOR
    BNE RDVC        ;BR IF A LINK
    SEC         ;SET END OF DIR
    RTS
;
RDVC    LDY VDLSEC      ;GET SECTOR
RVDGO
    STX CVDTRK      ;SET CUR TRACK
    STY CVDSEC      ;SET CUR SECTOR
    LDA #IBCRTS     ;GET CMD
    JSR DCBIO       ;GO DO I/O
    CLC
    RTS
    PAGE
;
;   WRVDIR – WRITE VOLUME DIRECTORY SECTOR
;
WRVDIR
    JSR MVVDBA
;
    LDX CVDTRK      ;CURRENT TRACK
    LDY CVDSEC      ;CURRENT SECTOR
    LDA #IBCWTS     ;WRITE COMMAND
    JMP DCBIO       ;GO DO I/O
;
;   MVVDBA – MOVE VOL DIR BUF ADR TO IOB
;
MVVDBA
    LDA AVOLDR      ;MOVE ADR
    STA IBBUFP
    LDA AVOLDR+1
    STA IBBUFP+1
    RTS
    PAGE
;
;   DCBIO – DO I/O FOR A DCB
;
DCBIO
    STX IBTRK       ;TRACK
    STY IBSECT      ;SECTOR
DCBIO2
    STA IBCMD       ;COMMAND
    CMP #IBCWTS
    BNE DCBIO1
    ORA DCBWRF
    STA DCBWRF
DCBIO1
    LDA DCBVOL      ;VOL
    EOR #$FF        ;UNINVERT VOL BITS
    STA IBVOL
    LDA DCBSLT      ;SLOT
    STA IBSLOT
    LDA DCBDRV      ;DRIVE
    STA IBDRVN
    LDA DCBSDL      ;LENGTH
    STA IBDLEN
    LDA DCBSDL+1
    STA IBDLEN+1
    LDA #1      ;IOB TYPE
    STA IBTYPE
;
    LDY AIOB        ;IOB ADR
    LDA AIOB+1
    JSR DISKIO      ;GO DO I/O
;
    LDA IBSMOD
    STA CCBVOL
    LDA #$FF        ;RESET VOL
    STA IBVOL
    BCS BADIO       ;BR IF BAD
    RTS         ;RTN IF GOOD
;
BADIO   LDA IBSTAT      ;GET STATUS
    LDY #CREVMM
    CMP #IBVMME     ;WAS IT VOLUME MISMATCH
    BEQ BD2     ;BR IF YES
    LDY #CREPRO
    CMP #IBWPER
    BEQ BD2
    LDY #CREIOE
BD2 TYA
    JMP ERRORB      ;GO RTN
    PAGE
;
;   LOCNXB – LOCATE NEXT BYTE
;
LOCNXB
    LDA DCBCRS      ;IS THE CURRENT RELATIVE SECTOR
    CMP DCBCMS      ;EQUAL TO THE CURRENT MEM SECTOR
    BNE LNB1        ;BR IF NOT EQ
    LDA DCBCRS+1
    CMP DCBCMS+1
    BEQ LNB8        ;BR IF REQD SECTOR IN MEM
;
LNB1                ;NEED A DIFFERENT SECTOR IN MEM
    JSR WRSECT      ;GO WRITE SECTOR(IF REQD)
;
LNB2    LDA DCBCRS+1        ;IS CURRENT REL SECTORY
    CMP DCBDFS+1        ;IS CURRENT DIRECTORY (LOW LIMIT)
    BCC LNB4        ;BR IF IN A PREVIOUS DIR
    BNE LNB3        ;BR IF MAYBE IN THIS ONE
    LDA DCBCRS      ;TEST LOW BYTES
    CMP DCBDFS
    BCC LNB4        ;BR IF IN PREVIOUS DIR
;
LNB3    LDA DCBCRS+1        ;IS CURRENT REL SECTOR
    CMP DCBDNF+1        ;IN CURRENT DIRECTOR (HI LIMIT)
    BCC LNB6        ;BR IF IN THIS ONE
    BNE LNB4        ;BR IF IN A NEXT DIR
    LDA DCBCRS
    CMP DCBDNF
    BCC LNB6        ;BR IF IN THIS ONE
;               ;REQD SECTOR IN A NEXT DIRECTORY
LNB4    JSR RDFDIR      ;GO READ NEXT FILE DIR
    BCC LNB2        ;BR NXT AVAIL
    RTS         ;RETURN IF EOF DIR
;
;
LNB6
    SEC         ;CALCULATE DISPL INTO DIR
    LDA DCBCRS      ;REQD REL SECTOR MINUS
    SBC DCBDFS
    ASLA            ;TIMES 2
    ADC #FDENT      ;PLUS DISPL TO 1ST
    TAY
    JSR MVFCBD      ;MOVE ADR TO ZPG
    LDA (ZPGFCB),Y  ;GET TRACK
    BNE LNB7        ;BR IF NOT ZERO
    LDA CCBREQ
    CMP #CRQWR      ;WRITE
    BEQ LNB7A
    SEC
    RTS
LNB7A   JSR GNWSEC      ;GO GET A NEW SECTOR
    JMP LNBCON
LNB7    STA DCBTRK      ;SET TRK INTO DCB
    INY
    LDA (ZPGFCB),Y  ;GET SECTOR
    STA DCBSEC      ;PUT INTO DCB
    JSR RDSECT      ;GO READ SECTOR
LNBCON  LDA DCBCRS      ;MOVE CUR REL SECTOR
    STA DCBCMS
    LDA DCBCRS+1        ;TO CUR MEM SECTOR
    STA DCBCMS+1
;
LNB8
    JSR MVFCBS      ;MOVE SECTOR BUFF ADR TO ZP
    LDY DCBCSB      ;GET SECT BYTE
    CLC         ;CARRY CLEAR = ALL OK
    RTS         ;DONE
    PAGE
;
;
GNWSEC              ;NEED NEW SECTOR
    STY TEMP2       ;SAVE DIR INDEX
    JSR GETSEC      ;GET A SECTOR
    LDY TEMP2
    INY
    STA (ZPGFCB),Y  ;SET NEW TRACK
    STA DCBSEC
    DEY
    LDA DCBATK
    STA (ZPGFCB),Y  ;SET NEW TRACK
    STA DCBTRK
;
    JSR MVFCBS
    JSR CLRSEC      ;GO CLEAR SECTOR
;
;
    LDA #$C0        ;INDICATE BOTH
    ORA DCBWRF      ;DIR AND SECTOR
    STA DCBWRF      ;MUST BE WRITTEN
    RTS         ;DONE
    PAGE
;
;   INCRRB – INCREMENT RELATIVE RECORD BYTE
;
INCRRB
    LDX DCBCRR      ;MOVE BYTE JUST READ OR WRITTEN
    STX CCBRRN
    LDX DCBCRR+1
    STX CCBRRN+1
    LDX DCBCRB      ;X=REL BYTE (LOW)
    LDY DCBCRB+1        ;Y=REL BYTE HI
    STX CCBBYT
    STY CCBBYT+1
    INX         ;INC REL BYTE (LOW)
    BNE INCR1       ;BR IF NO CARRY
    INY         ;INC REL BYTE (HI)
;
INCR1   CPY DCBRCL+1        ;REL BYTE=REC LENGTH
    BNE INCR2       ;BR IF NOT
    CPX DCBRCL      ;TEST LOW BYTES
    BNE INCR2
    LDX #0
    LDY #0      ;RESET REL BYTE TO ZERO
    INC DCBCRR      ;AND INCR
    BNE INCR2       ;RELATIVE RECORD
    INC DCBCRR+1
;
INCR2   STX DCBCRB      ;SAVE NEW RELATIVE BYTE
    STY DCBCRB+1    
;
    RTS
    PAGE
;
;   INCSCB – INCREMENT SECTOR BYTE
;
INCSCB
    INC DCBCSB      ;INC SECTOR BYTE
    BNE INCS2       ;BR IF NOT FULL
    INC DCBCRS      ;AND INCR
    BNE INCS2       ;RELATIVE SECTOR
    INC DCBCRS+1    
;
;
INCS2
    RTS         ;DONE
    PAGE
;
;   MIBDA – MOVE AND INCREMENT CCBDAT
;
MIBDA
    LDY CCBBBA      ;Y=ADR LOW
    LDX CCBBBA+1        ;X=ADR HI
    STY ZPGFCB      ;PUT ADR INTO ZPG
    STX ZPGFCB+1
;
    INC CCBBBA      ;INC ADR LOW
    BNE MIB1        ;BR IF NOT ZERO
    INC CCBBBA+1        ;INC ADR HI
MIB1    RTS         ;DONE
;
;   DTBLN – DCREMENT BLOCK LENGTH AND TEST ZERO
;
DTBLN
    LDY CCBBLN      ;GET LEN LOW
    BNE DTB1        ;BR IF NOT ZERO
    LDX CCBBLN+1        ;GET LEN HI
    BEQ DTB2        ;BR IF LEN=0
    DEC CCBBLN+1        ;DEC LEN (HIGH)
DTB1    DEC CCBBLN      ;DEC LEN (LOW)
    RTS         ;DONE
;
DTB2    JMP GOODIO      ;FINISHED BLOCK
    PAGE
;
;   FNDFIL – FIND FILE NAME IN VOLUME DIR
;
FNDFIL
    JSR RDVTOC      ;GO GET VTOC
    LDA CCBFN1      ;MOVE FN PTR
    STA ZPGFCB      ;TO ZERO PAGE
    LDA CCBFN1+1
    STA ZPGFCB+1
    LDA #1
FF1 STA TEMP2
    LDA #0
    STA DCBVDR
    CLC
FF2
    INC DCBVDR
    JSR RDVDIR      ;GO GET VDIR SECTOR
    BCS FF4A
    LDX #0      ;SET FOR 1ST FILE
;
FF3 STX TEMP1       ;SAVE INDEX
    LDA VDFILE,X        ;GET FILE TRK
    BEQ FF6     ;BR IF LAST ENTRY
    BMI FF7     ;BR DELETED ENTRY
    LDY #0      ;X=X+3
    INX
    INX
FF4 INX
    LDA (ZPGFCB),Y  ;GET FN CHAR
    CMP VDFILE,X        ;COMPARE TO ENTRY CHAR
    BNE FF5     ;BR IF NOT SAME
    INY
    CPY #30     ;ALL 30 CHARS
    BNE FF4     ;BR IF NOT
    LDX TEMP1       ;GET INDEX
    CLC         ;FILE FOUND
    RTS         ;RETURN
;
FF5
    JSR VDINC
    BCC FF3
    BCS FF2
;
FF6 LDY TEMP2       ;LOOKING FOR DELETED
    BNE FF1     ;BR IF NOT (DO)
;
FF7 LDT TEMP2       ;LOOKING FOR EMPTY
    BNE FF5     ;BR IF NOT
;
MVFN
    LDY #0      ;HAVE NEW ENTRY
    INX
    INX
FF8 INX
    LDA (ZPGFCB),Y  ;MOVE FILE NAME
    STA VDFILE,X
    INY
    CPY #30
    BNE FF8
;
    LDX TEMP1       ;GET INDEX
    SEC         ;SET NOT OLD
    RTS         ;DONE
VDINC
    CLC
    LDA TEMP1
    ADC #35
    TAX
    CPX #VDFLEN
    RTS
FF4A
    LDA #0
    LDY TEMP2
    BNE FF1
    JMP ERROR9
    PAGE
;
;   GETSEC – GET A SECTOR
;
GETSEC
    LDA DCBATK      ;GET ALLOCATED TRK
    BEQ GSS1        ;BR IF NONE
;
GSO
    DEC DCBALS      ;DECREMENT SECTOR NO
    BMI CS2     ;BR IF NO SECTORS REM
;
    CLC
    LDX #4      ;4 BYTE SHIFT
GS1 ROL DCBABM-1,X  ;SHIFT BYTE LEFT
    DEX
    BNE GS1
    BCC GS0     ;BR IF NO SECTOR
;
    INC DCBNSA
    BNE GS1A
    INC DCBNSA+1
GS1A
    LDA DCBALS      ;GET ALLOCATED SECTOR
    RTS         ;RETURN
;
CS2 LDA #0      ;CLEAR ALLOCATED
    STA DCBATK      ;TRK
;
GSS1    LDA #0      ;SET SEARCH STATE=0
    STA TEMP3
    JSR RDVTOC      ;GET VTOC
;
GS2
    CLC
    LDA VALCA1      ;GET LAST ALLOCATED TRK
    ADC VALCA2      ;AD (+1) OR (-1)
    BEQ GS3     ;BR IF DECK TO ZERO
    CMP VNOTRK
    BCC GS5     ;BR IF NOT AT OUTER LIMIT
    LDA #$FF        ;SET (-1)
    BNE GS4
GS3 LDA TEMP3       ;GET SEARCH STATE
    BNE ERR9        ;BR IF NOT ZERO
    LDA #1      ;SET (+1)
    STA TEMP3       ;SET SEARCH STATE = 1
GS4 STA VALCA2      ;SET NEW (+1) OR (-1)
    CLC
    ADC #17     ;ADD VTOC TRK NO
GS5 STA VALCA1      ;SET NEW LAST ALLOCATED
    STA DCBATK      ;PUT IN DCB
;
    TAY         ;ALLOCATED TRACK
    ASLA            ;TIME 4
    ASLA
    TAY
    LDX #4
    CLC
GS6 LDA VSECAL+3,Y  ;MOVE BIT MAP BYTE
    STA DCBABM-1,X
    BEQ GS7     ;BR IF NO BITS ON
    SEC         ;SET HAVE A SECTOR
    LDA #0      ;CLEAR VTOC BYTE
    STA VSECAL+3,Y
GS7 DEY
    DEX
    BNE GS6     ;BR IF MORE TO MOVE
    BCC GS2
    LSR WRVTOC      ;GO WRITE VTOC
    LDA VNOSEC      ;GET NO SECTORS
    STA DCBALS      ;SET IN DCB SECTOR BYTE
    BNE GS0     ;GO ALLOCATED SECTOR
ERR9    JMP ERROR9
    PAGE
;
;   FRETRK – FREE TRACK OF SECTORS
;
FRETRK
    LDA DCBATK      ;GET ALLOCATED TRACK
    BNE FT1     ;BR IF NONE
    RTS         ;DONE
FT1 PHA
    JSR RDVTOC      ;GET VTOC
    LDY DCBALS      ;GET SECTORS
    PLA         ;GET TRACK
    CLC         ;SET FREE
    JSR FRESEC      ;GO FREE
    LDA #0      ;CLEAR ALLOCATED TRK
    STA DCBATK
    JMP WRVTOC      ;WRITE VTOC
;
;   FRESEC – FREE A SECTOR
;       A=TRK, Y=SECTOR, C=ON/OFF
;
FRESEC
FS1 LDX #252        ;4 BYTE SHIFT
FS2 ROR DCBABM-252,X    ;SHIFT IN CARRY
    INX         ;NEXT BYTE
    BNE FS2     ;BR IF NOT DONE
    INY         ;INC SECTOR NO
    CPY VNOSEC      ;NORMAL
    BNE FS1     ;BR IF NOT
;
    ASLA            ;TRACK*4
    ASLA
    TAY
    BEQ FS4
    LDX #4
FS3 LDA DCBABM-1,X  ;GET BIT MAP BYTE
    ORA VSECAL+3,Y  ;GET BIT MAP BYTE
    STA VSECAL+3,Y  ;OR WITH VTOC BM
    DEY
    DEX
    BNE FS3
FS4 RTS         ;DONE
    PAGE
;
;   LOCSEC – LOCATE SECTOR FOR RECORD I/O
;
;   RELSEC = (REL REC * RECLEN + RELBYTE)/256
;   SECBYT = REMAINDER
;
LOCSEC
    LDA CCBRRN      ;RELATIVE RECORD NUMBER
    STA DCBCSB      ;TO CSB FOR MULT
    STA DCBCRR      ;AND CRR FOR SAVE
    LDA CCBRRN+1
    STA DCBCRS
    STA DCBCRR+1
    LDA #0
    STA DCBCRS+1        ;HIGH CRS=0
    LDY #16     ;16 BIT MULT
;
LS1 TAX         ;SAVE MS BYTE
    LDA DCBCSB
    LSRA            ;IF NO CARRY THEN NO PART PROD
    BCS LS1A
    TXA
    BCC LS2
LS1A    CLC
    LDA DCBCRS+1        ;FPORM PARTIAL PROD
    ADC DCBRCL
    STA DCBCRS+1
    TXA
    ADC DCBCRL+1
;
LS2 RORA            ;MULT BY 2
    ROR DCBCRS+1
    ROR DCBCRS
    ROR DCBCSB
    DEY         ;DEC BIT COUNT
    BNE LS1     ;BR IF MORE BITS
;
    LDA CCBBYT      ;LADD REL BYTE RESULT
    STA DCBCRB      ;(SAVE REL BYTE)
    ADC DCBCSB
    STA DCBCSB
    LDA CCBBYT+1
    STA DCBCRB+1        ;(SAVE REL BYTE)
    ADC DCBCRS
    STA DCBCRS
    LDA #0
    ADC DCBCRS+1
    STA DCBCRS+1
    RTS
    PAGE
ERROR1  LDA #CREFUN
    BNE ERRORA
ERROR2  LDA #CRERR
    BNE ERRORA
ERROR3  LDA #CREMRE
    BNE ERRORA
ERROR4  LDA #CREPRO
    BNE ERRORA
ERROR5  LDA #CREEOF
    BNE ERRORA
ERROR6  LDA #CREFNF
    BNE ERRORA
ERROR9  LDA #CRENSA
    BNE ERRORA
ERROR10 LDA #CREFLK
    BNE ERRORA
GOODIO  LDA CCBSTA
    CLC         ;CARRY=CLR
    BCC RETURN      ;GO RETURN
ERRORA
ERRORB  SEC         ;CARRY=SET
RETURN
    PHP
    STA CCBSTA      ;SET STA
    JSR RTNFCB      ;GO RTN FCB
    PLP         ;GET STATUS
    LDX ENTSTK      ;GET ENT STACK
    TXS         ;RESTORE STACK
    RTS         ;DONE
EC2
    PAGE
;
;   MISC DOS WORK CELLS
;
CVDTRK  DB  0       ;CUR VOL DIR TRK
CVDSEC  DB  0       ;CUR VOL DIR SECTOR
CURCCB  DB  0,0     ;CURRENT CCB ADR
 
ENTSTK  DB  0       ;ENTRY STACK POINTER
TEMP1   DB  0       ;TEMP BYTE 1
TEMP2   DB  0       ;TEMP BYTE 2
TEMP3   DB  0       ;TEMP BYTE 3
ENTSLT  DB  0       ;BOOT SLOT SAVED
ALC10S  DB  0,0,$F8,$FF ;ALLOCATATION TRACK BIT MAP
CVTAB   DB  1,10,100        ;CONVERSION TABLE
FTTAB   DB11    "TBAI"      ;FILE TYPE CONVERSION TABLE
VOLUMES DB11    " EMULOV KSID"
VML EQU *-VOLMES-1
    PAGE
;
;   VTOC RECORD AREA
;
VTOC
VDOST   DB  2       ;DOS TYPE
VDIRTK  DB  17      ;COLUME DIRECTORY SECTOR
VDIRSC  DB  12      ;VOLUME DIRECTORY SECTOR
VDOSRN  DB  2       ;DOS RELEASE NUMBER
    DB  0       ;SPARE
    DB  0       ;SPARE
VVOLNO  DB  0       ;VOLUME NUMBER
    RMB 32      ;SPARE
VTDMS   DB  122     ;MAX SECTORS IN A FILE DIR
VSPARE  RMB 8       ;SPARES
;
VALCA1  DB  17      ;ALOCATION ALGORITHM BYTE 1
VALCA2  DB  1       ;AA BYTE 2
VALCA3  DB  0       ;AA BYTE 3
VALCA4  DB  0       ;AA BYTE 4
VNOTRK  DB  35      ;NO TRACKS ON VOL
VNOSEC  DB  13      ;NO SECTORS PER TRACK
VSECLN  DB  @@256       ;NO BYTES PER SECTOR
;
VSECAL  EQU *       ;SECTOR ALLOCATION AREA
;               SECTORS ALLOCATED BY BIT MAP
;               4 BYTES OF BITS PER TRACK
;               LEFT MOST BIT REPRESENTS SECTOR N
;               WHERE N=NO SECTORS PER TRACK
;
;
    PAGE
    ORG VTOC+256
;
;   VOLUME DIRECTORY AREA
;
VOLDIR
VDTCDE  DB  2       ;VOLUME DIRECTORY TYPECODE
VDLTRK  RMB 1       ;VD LINK TRACK
VDLSEC  RMB 1       ;VD LINK SECTOR
VDNF    RMB 1       ;VD NUMBER FILES THIS SECTOR
VDSPAR  RMB 7       ;SPARES
;
VDFILE  EQU *       ;FILE ALLOCATION AREA (7 FILES)
;               EACH FILE
;                   FILE DIR TRK
;                   FILE DIR SECTOR
;                   FILE USE CODE
;                FILE NAME (30)
;               FILE SECTOR COUNT (2)
;
    ORG VOLDIR+256
VDEND   EQU *
VDLEN   EQU *-VOLDIR
VDFLEN  EQU *-VDFILE
    PAGE
;
;   COMMAND CONTROL BLOCK (CCB)
;
CCB
CCBREQ  RMB 1       ;USER REQUEST BYTE
CRQNUL  EQU 0       ;0-NO REQUEST
CRQOPN  EQU 1       ;1-OPEN FILE
CRQCLS  EQU 2       ;2-CLOSE FILE
CRQRD   EQU 3       ;3-READ DATA
CRQWR   EQU 4       ;WRITE DATA
CRQDEL  EQU 5       ;5-DELETE FILE
CRQDIR  EQU 6       ;6-READ DIRECTORY
CRQLCK  EQU 7       ;7-LOCK FILE
CRQUNL  EQU 8       ;8-UNLOCK FILE
CRQRNM  EQU 9       ;9-RENAME
CRQPOS  EQU 10      ;10-POSITION FILE
CRQFMT  EQU 11      ;11-FORMAT
CRQVAR  EQU 12      ;12-VERIFY
CRQMAX  EQU 13
;
CCBBSA              ;FORMAT – BOOT START ADR PAGE
CCBRQM  RMB 1       ;REQUEST MODIFIER BYTE
CRMNUL  EQU 0       ;NO MODIFIER
CRMNBT  EQU 1       ;R/W – 1 – NEXT BYTE
CRMNBL  EQU 2       ;R/W – 2 – NEXT BLOCK
CRMSBT  EQU 3       ;R/W – 3 – SPECIFC BYTE
CRMSBL  EQU 4       ;R/W – 4 – SPECIFIC BLOCK
CRMMAX  EQU 5
;
CCBRRN              ;I/O – RELATIVE RECORD NUMBER
CCBFN2              ;RENAME – FILE NAME 2 PTR
CCBRLN  RMB 2       ;OPEN – RECORD LENGTH
;
CCBBYT              ;I/O – RELATIVE RECORD NO(2 BYTES)
CCBVOL  RMB 1       ;OPEN – VOL NO.
CCBDRV  RMB 1       ;OPEN – DRIVE
;
CCBBLN              ;I/O – BLOCK LENGTH (2 BYTES)
CCBSLT  RMB 1       ;OPEN – SLOT NO.
CCBFUC  RMB 1       ;OPEN - FILE USE CODE
;
CCBFN1              ;OPEN, DELETE, LOCK, UNLOCK, RENAME – FILENAME P
CCBBBA              ;BLCOKK I/O – BLOCK BUFFER PTR
CCBDAT  RMB 2       ;BYTE I/O – DTA BYTE
;
CCBSTA  RMB 1       ;RESULT STATUS
CREFUN  EQU 1       ;FCB UNALLOCATED
CRERR   EQU 2       ;CCB REQ RANGE ERR
CREMRE  EQU 3       ;REQ MOD RANGE ERR
CREPRO  EQU 4       ;WRITE PROTECT
CREEOF  EQU 5       ;END OF FILE ON READ
CREFNF  EQU 6       ;FILE NOT FOUND
CREVMM  EQU 7       ;VOL MIS MATCH
CREIOE  EQU 8       ;I/O ERR
CRENSA  EQU 9       ;NO SECTORS AVAILABLE
CREFLK  EQU 10      ;FILE LOCKED
;
CCBSM   RMB 1       ;STATUS MODIFIER
CCBFCB  RMB 2       ;FCB PTR
CCBDBP  RMB 2       ;DIR BUF PTR
CCBSBP  RMB 2       ;SECTOR BUF PTR
CCBSPR  RMB 4       ;SPARE
CCBLEN  EQU *-CCB       ;CCB LENGTH
CFCBAD  EQU CCBFCB
CFCBDR  EQU CCBDBP
CFCBSB  EQU CCBSBP
    PAGE
;
;   FILE CONTROL BLOCK (FCB) DEFINITION
;       DCB – FILE DATA CONTROL BLOCK
;
FCB
;
;   DATA CONTROL BLOCK
;
FCBDCB
DCBFDT  RMB 1       ;1ST FILE DIRECTORY TRACK
DCBFDS  RMB 1       ;1ST FILE DIRECTORY SECTOR
DCBCDT  RMB 1       ;CURRENT FILE DIRECTORY
DCBCDS  RMB 1       ;CURRENT FILE DIRECTORY
DCBWRF  RMB 1       ;WRITE REQD FLAG
;               ;$80=WRITE FILE DIR
;               ;$40=WRITE SECTOR DIR
DCBTRK  RMB 1       ;SECTOR TRACK ADR
DCBSEC  RMB 1       ;SECTOR ADR
DCBVDR  RMB 1       ;VOL DIR REC
DCBVDI  RMB 1       ;VOL DIR INDEX
DCBDMS  RMB 2       ;MAX NO DIRECTORY SECTORS
DCBDFS  RMB 2       ;CURRENT DIR 1ST REL SECTRO
DCBDNF  RMB 2       ;REL SECTOR OF NXT DIR
DCBCMS  RMB 2       ;SECTOR CURRENTLY IN MEMORY
DCBSDL  RMB 2       ;SECTOR DATA LENGTH
DCBCRS  RMB 2       ;CURRENT RELATIVE SECTOR
DCBCSB  RMB 2       ;REL SECTOR OF NXT DIR
DCBRCL  RMB 2       ;SECTOR CURRENTLY IN MEMORY
DCBCRR  RMB 2       ;SECTOR DATA LENGTH
DCBCRB  RMB 2       ;CURRENT RELATIVE SECTOR
DCBNSA  RMB 2       ;NO SECTORS ALLOCATED
;
DCBALS  RMB 1       ;ALLOCATION SECTOR BYTE
DCBATK  RMB 1       ;ALLOCATION TRACK
DCBABM  RMB 4       ;ALLOCATION TRACK SECTOR BIT MAP
;
DCBFUC  RMB 1       ;FILE USE CODE
DCBSLT  RMB 1       ;SLOT NUMBER
DCBDRV  RMB 1       ;DRIVE NUMBER
DCBVOL  RMB 1       ;VOLUME DRIVER
DCBVTN  RMB 1       ;VTOC TRACK NUMBER
;
DCBSPR  RMB 3       ;SPARES
;
DCBLEN  EQU *-FCBDCB        ;DCB LENGTH
FCBLEN  EQU *-FCB       ;FCB LENGTH
    PAGE
;
;   DOS PATCH AREA 1
SDP1
EDP1    EQU ORG2-2
;
;   DOSLDR – DOS LOADER AND WRITTER
;
    ORG ORG2
DOSLDR
;   GARBAGED BOOT REC 0 HERE
    RMB 254
GRSPG   DB  0
GRPGC   DB  0
    PAGE
SC3
;
;   READ DOS AFTER BOOT
;;
    STX IBSLOT      ;SET BOOT SLOT
    STX IBPSLT      ;SET PREVIOUS SLOT
    LDA #1      ;SET PREV DRIVE
    STA IBPDRV
    STA IBDRVN
;
    LDA NDPGS       ;COPY NO PAGES TO GET
    STA BRWCNT
    LDA #0
    STA IBTRK       ;SET TRACK 0
;
    LDA BSDSEC      ;COPY START DOS SECTOR
    STA IBSECT
;
    LDA BGNDOS      ;COPY STARTR DOS ADR
    STA IBBUFP+1
;
    LDA #IBCRTS     ;SET READ
    STA IBCMD
;
    TXA         ;SET PREV TRACK = 0
    LSRA
    LSRA
    LSRA
    LSRA
    TAX
    LDA #0
    STA $4F8,X
    STA $478,X
    JSR BOOTIO      ;GO READ DOS
;
;   DOSINT – INITIALIZE DOS
;
DOSINT
    LDX #$FF
    TXS
    STX IBVOL
    JSR SETVID
    JSR SETKBD
;
DI3 JMP DOSREL      ;GO TO POST INIT ROUTINE
    PAGE
WBOOT
    LDA IBBUFP+1        ;GET START OF DOS
    STA BGNDOS      ;SAVE IR
    SEC
    LDA ADOSLD+1        ;CALCULATE
    SBC BGNDOS
    STA NDPGS       ;NO DOS PAGES
;
    LDA #0
    STA IBTRK       ;TRACK=0
    STA IBSECT      ;SECTOR=0
    STA IBBUFP
;
    LDA ADOSLD+1        ;GET BOOT START ADR
    STA IBBUFP+1        ;TO BUFP
    STA GRSPG       ;TO GARBAGE RECORD
;
    LDA #10     ;NO OF BOOT PAGES
    STA BRWCNT      ;TO BOOT I/O COUNTER
    STA BSDSEC
    LDA #$48
    STA GRPGC
;
    LDA #IBCWTS     ;SET WRITE
    STA IBCMD
;
    JSR BOOTIO      ;GO WRITE BOOT SECTORS
;
    LDA BGNDOS      ;SET START OF DOS
    STA IBBUFP+1
;
    LDA NDPGS
    STA BRWCNT
    JSR BOOTIO      ;GO WRITE DOS
;
    RTS         ;DONE
    PAGE
BOOTIO
    LDA BAIOB+1
    LDY BAIOB
    JSR DISKIO
 
    LDY IBSECT      ;GET SECTOR
    INY         ;INCREMENT TO NEXT
    CPY #13     ;AT END OF TRACK
    BNE BI01        ;BR IF NOT SECTOR ZERO
    LDY #0      ;SET TO SECTOR ZERO
    INC IBTRK
BI01    STY IBSECT      ;SET NEXT SECTOR
;
    INC IBBUFP+1        ;INCREMENT BUFFER POINTER
    DEC BRWCNT      ;DECREMENT PAGE COUNTER
    BNE BOOTIO      ;BR IF NOT DONE
    RTS
;
    PAGE
;
;   DOS PATCH AREA 1
;
DP1 EQU *
    BOUND 256
    ORG *-$20
EC3
NDPGS   DB  0
BRWCNT  DB  0
BSDSEC  DB  0
BGNDOS  DB  0
BAIOB   DB  @@IOB
ADOSLD  DB  @@DOSLDR
    PAGE
;
;   IOB – INPUT / OUTPUT CONTROL BLOCK
;         THE IOB IS USED FOR THE INTERFACE
;         BETWEEN DOS AND THE DISK I/O ROUTINES
;
IOB
IBTYPE  DB  1       ;IOB TYPE CODE
IBSLOT  DB  7       ;CONTROLLER SLOT NO.
IBDRVN  DB  0       ;DRIVE NUMBER
IBVOL   DB  $FF     ;VOLUME NUMBER
IBTRK   DB  0       ;TRACK NUMBER
IBSECT  DB  0       ;SECTOR NUMBER
IBDCTP  DB  @@DCT
IBBUFP  DB  @@0     ;POINTER TO BUFFER
IBDLEN  DB  @@256       ;DATA LENGTH
IBCMD   DB  0       ;COMMAND 
IBCNUL  EQU 0       ;0-NULL COMMAND
IBCRTS  EQU 1       ;1-READ TRACK, SECTOR
IBCWTS  EQU 2       ;2-WRITE TRACK, SECTOR
IBFMT   EQU 4       ;4-FORMAT DISK
IBBOOT  EQU 8       ;8-WRITE BOOT
IBSTAT  DB  0       ;STATUS 
IBRERR  EQU $80     ;READ ERR
IBDERR  EQU $40     ;DRIVE ERR
IBVMME  EQU $20     ;VOLUME MISMATCH
IBWPER  EQU $10     ;WRITE PROTECT ERROR
IBSMOD  DB  0       ;STATUS MODIFIER BYTE
IBPSLT  DB  0       ;PREVIOUS SLOT
IBPDRV  DB  0       ;PREVIOUS SLOT
IBSPAR  RMB 2       ;IOB SPARES
DCT DB  0,1,$EF,$D8
    PAGE
;
;   FILE DIRECTORY DEFINITION
;
    ORG 0
FILDIR
FDUCDE  RMB 1       ;FILE USE CODE
FDLTRK  RMB 1       ;LINK TO NXT DIR TRACK
FDLSEC  RMB 1       ;LINK TO NEXT DIR SECTOR
FDNSA   RMB 1       ;NO SECTOR ALLOCATED
FDLSDL  RMB 1       ;LAST SECTOR DATA LENGTH
FDFRS   RMB 2       ;1ST RELATIVE SECTOR IN THIS DIR
FDSPAR  RMB 5       ;SPARES
;
FDENT   RMB 1       ;START OF FILE ENTRIES (122)
FDTRK   EQU 0       ;TRACK 
FDSEC   EQU 1       ;SECTOR
;
FDLAST  EQU FILDIR+256
    PAGE
    END

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎