    title   CUBIX 6809 Operating System
*
* CUBIX Operating System for the 6809
*
* ?COPY.TXT 1983-2005 Dave Dunfield
* **See COPY.TXT**.
*
* asmode=dist OR demo
    ifeq    asmode,dist
* MEMORY LOCATIONS FOR DISTRIBUTION (NON-PORTED) ROM
ROM EQU $E000       OS FIRMWARE
RAM EQU ROM-1024    OS LOCAL STORAGE (1K)
USRRAM  EQU $2000       START OF USER SUPPLIED RAM
USREND  EQU ROM-1       RAMTEST STOPS HERE
    endif
    ifeq    asmode,demo
* MEMORY LOCATIONS FOR THE DEMO SYSTEM USING EXAMPLE DRIVERS
ROM EQU $E000       OS FORMWARE
RAM EQU ROM-1024    OS LOCAL STORAGE
USRRAM  EQU $2000       START OF USER SUPPLIED RAM
USREND  EQU ROM-1       RAMTEST STOPS HERE
dr_file set sample.sys
    endif
* MISC CONSTANTS
NDEV    EQU 8       NUMBER OF SERIAL DEVICES SUPPORTED
NDSK    EQU 4       # OF DISK DRIVES SUPPORTED
DIRSEC  EQU 0       DIRECTORY STARTS HERE
LNKSEC  EQU 1       STARTING LINK SECTOR ON DISK
DEFATR  EQU %11110000   DEFAULT FILE ATTRIBUTES
* RETURN CODES
RCBOP   EQU 1       BAD OPERAND
RCNOTF  EQU 2       FILE NOT FOUND
RCPRO   EQU 3       FILE PROTECTION VIOLATION
RCORE   EQU 4       NOT OPEN FOR READ
RCOWE   EQU 5       NOT OPEN FOR WRITE
RCEOF   EQU 6       END OF FILE ENCOUNTERED
RCEXI   EQU 7       FILE ALREADY EXISTS
RCNOS   EQU 8       NO DISK SPACE AVAILABLE
RCDSK   EQU 9       DISK ERROR
RCDEV   EQU 10      INVALID DEVICE
RCDNL   EQU 11      DOWNLOAD FAILURE
RCCMD   EQU 255     BAD COMMAND
* FILE PERMISSIONS
RPERM   EQU %10000000   READ PERMISSION
WPERM   EQU %01000000   WRITE PERMISSION
EPERM   EQU %00100000   EXECUTE PERMISSION
DPERM   EQU %00010000   DELETE PERMISSION
* DISK CONTROL BLOCK DESCRIPTION
    ORG 0
DRIVE   RMB 1       DRIVE ID
NCYL    RMB 1       # TRACKS
NHEAD   RMB 1       # HEADS
NSEC    RMB 1       # SECTORS/TRACK
CYL RMB 1       CURRENT CYLINDER
HEAD    RMB 1       CURRENT HEAD
SEC RMB 1       CURRENT SECTOR
CSIZE   EQU *
* DIRECTORY ENTRY DESCRIPTION
    ORG 0
DPREFIX RMB 8       DIRECTORY PREFIX
DNAME   RMB 8       FILENAME
DTYPE   RMB 3       FILETYPE
DDADR   RMB 2       DISK ADDRESS
DRADR   RMB 2       RUN ADDRESS
DATTR   RMB 1       FILE ATTRIBUTES
* FILE CONTROL BLOCK DESCRIPTION
    ORG 0
OTYPE   RMB 1       TYPE OF OPEN (READ/WRITE ETC.)
ODRIVE  RMB 1       DRIVE FILE IS ON
OFIRST  RMB 2       FIRST SECTOR IN ILE
OSECTOR RMB 2       SECTOR BEING READ/WRITTEN
OLSTSEC RMB 2       LAST SECTOR READ/WRITTEN
OOFFSET RMB 2       OFFSET INTO SERIAL BUFFER
OSIZ    EQU *
* RAM VARIABLES
    ORG RAM
INBUFF  RMB 80      INPUT BUFFER
IRAM    EQU *       START OF INITIALIZED RAM
DCTRL   RMB CSIZE*NDSK  DRIVE CONTROL BLOCKS
CONIN   RMB 1       SELECTED CONSOLE INPUT
CONOUT  RMB 1       SELECTED CONSOLE OUTPUT
* DITAB MARKS START OF VECTOR TABLE
* SERIAL DEVICE DRIVERS
DITAB   RMB NDEV*2      DEVICE INPUT DRIVERS
DOTAB   RMB NDEV*2      DEVICE OUTPUT DRIVERS
* DISK DRIVERS
XHOME   RMB 2       DISK HOME HEAD ROUTINE
XRDSEC  RMB 2       DISK READ SECTOR ROUTINE
XWRSEC  RMB 2       DISK WRITE SECTOR ROUTINE
XFORMAT RMB 2       DISK FORMAT ROUTINE
* MACHINE VECTORS
SWIVEC  RMB 2       SWI HANDLER VECTOR
SWI2VEC RMB 2       SWI2 INTERRUPT VECTOR
SWI3VEC RMB 2       SWI3 INTERRUPT VECTOR
IRQVEC  RMB 2       IRQ HANDLER VECTOR
FIRQVEC RMB 2       FIRQ HANDLER VECTOR
NMIVEC  RMB 2       NMI HANDLER VECTOR
* MSGFLG MARKS START OF FLAG TABLES
MSGFLG  RMB 1       MESSAGE ENABLED FLAG
DBGFLG  RMB 1       DEBUG FLAG
TRCFLG  RMB 1       TRACE ENABLED FLAG
NUMFLG  EQU 3       # FLAGS SUPPORTED
* DEFAULT DIRECTORY
DEFDRV  RMB 1       DEFAULT DRIVE
DEFDIR  RMB 8       DEFAULT DIRECTORY
* SYSTEM DIRECTORY
SYSDRV  RMB 1       SYSTEM DRIVE
SYSDIR  RMB 8       SYSTEM DIRECTORY
* NON-INITIALIZED GLOBAL RAM
FDRIVE  RMB 1       CURRENT DISK DRIVE
PREFIX  RMB 8       DIRECTORY PREFIX
FNAME   RMB 8       FILENAME
FTYPE   RMB 3       FILETYPE
TEMP    RMB 2       TEMPORARY STORAGE
TEMP1   RMB 2       MORE TEMPORARY STORAGE
TEMP2   RMB 2       STILL MORE
TEMP3   RMB 2       STILL MORE
TEMP4   RMB 2       STILL MORE
SAVB    RMB 1       CALLERS 'B' REGISTER
SAVX    RMB 2       CALLERS 'X' REGISTER
SAVY    RMB 2       CALLERS 'Y' REGISTER
SAVDRV  RMB 1       CALLERS ACTIVE DRIVE
SAVSTK  RMB 2       CALLERS STACK POINTER
WRKCHG  RMB 1       WORK SECTOR CHANGED
WRKDRV  RMB 1       CURRENT WORK SECTOR DRIVE
WRKSEC  RMB 2       CURRENT WORK SECTOR
CMDDRV  RMB 1       CURRENT COMMAND FILE DRIVE
CMDSEC  RMB 2       CURRENTLY OPEN COMMAND FILE SECTOR
CMDOFF  RMB 2       OFFSET INTO COMMAND FILE SECTOR
CMDSTK  RMB 2       COMMAND PROCESSOR STACK PTR
CMDRC   RMB 1       COMMAND FILE RETURN CODES
OLDSTK  RMB 2       STACK FROM BEFORE TEMP ENTRY
SDRIVE  RMB 1       CURRENTLY SELECTED DRIVE
ERRCNT  RMB 1       DISK ERROR RETRY COUNT
CMDBUF  RMB 80      COMMAND BUFFER PARAMETER SAVE AREA
STACK   EQU RAM+512     SYSTEM STACK
WRKSPC  EQU STACK       WORK AREA
*
    ORG ROM
* MISC FIXED CONSTANTS
ROMCHK  FDB $FFFF       BLANK SPACE TO INSERT CHECKSUM
    ifeq    asmode,test
    ldd #ssr
    std >tvector
    jmp begin
    endif
MBASE   FDB USRRAM      BASE MEMORY ADDRESS
*
* HARDWARE INITIALIZATION ROUTINE
*
DOINIT  LDY #IRAM       POINT TO INITIALIZED RAM
    JMP HWINIT      INIT HARDWARE
*
* APPLICATION PROGRAM INTERFACE
*
SSR STB >SAVB       APPLICS SAVED 'B'
    STX >SAVX       APPLICS SAVED 'X'
    STY >SAVY       APPLICS SAVED 'Y'
    LDB >SDRIVE     GET DOS DRIVE
    STB >SAVDRV     SET SAVED DRIVE
    LEAY    10,S        ADDR OF SAVED PC
    LDX ,Y      GET IT
    LDB ,X+     GET OPERAND BYTE
    STX ,Y      SAVE UPDATED PC
    CMPB    #NUMSSR     IS IT A VALID CALL #
    BHS INVSSR      INVALID CALL
    ASLB            DOUBLE FOR TWO BYTE ENTRIES
    LDX #SSRTAB     OFFSET TO IT
    ABX         UNSIGNED ADD
    LDD ,X      GET ADDRESS
    STD >TEMP       SAVE SO WE CAN EXEC
    STY >SAVSTK     SAVE STACK POINTER
    LDA >DBGFLG     DEBUGGING?
    BNE DBGSSR      YES, OUTPUT DATA
    PULS    CC,A,B,DP,X,Y,U RESTORE APPLICS REGS
    JMP [TEMP]      EXECUTE SYSTEM CALL
DBGSSR  JSR WRLIN       OUTPUT LINE
    FCCZ    'SSR '
    LDX ,Y      RECOVER PC
    LDB -1,X        GET NUMBER BACK
    JSR WRDEC8      OUTPUT
    JSR WRLIN
    FCCZ    ' - '
    PULS    CC,A,B,DP,X,Y,U
    BSR DMPREG1     DISPLAY REGS
    JMP [TEMP]
INVSSR  TFR Y,S     FIX STACK
    JSR WRLIN       OUTPUT LINE
    FCCZ    'Invalid SSR '
    JSR WRDEC8      OUTPUT
    JSR WRLIN       OUTPUT LINE
    FCCZ    ' at $'
    LDD ,S++        GET ADDR
    SUBD    #2      BACK TO ADDRESS
    JSR WRHEXW      OUTPUT
    JSR LFCR        NEW LINE
    JMP DOSKCM      RE-ENTER, INSURE NO COMMAND
DMPREG  BSR DMPREG1     BSR SO PC ON STACK,4
    RTS
* DEBUG ROUTINE
DMPREG1 PSHS    CC,A,B      SAVE REGS
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    'PC='
    LDD 5,S     GET PC
    SUBD    #2      BACK UP TO SSR ADDRESS
    JSR WRHEXW      OUTPUT HEX WORD
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    ' CC='
    LDA ,S      GET CONDITION CODE
    JSR WRHEX       OUTPUT HEX BYTE
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    ' DP='
    TFR DP,A        GET DIRECT PAGE
    JSR WRHEX       OUTPUT HEX BYTE
    JSR WRLIN       OUTPUT MESSAHE
    FCCZ    ' A='
    LDA 1,S     GET SAVED 'A'
    JSR WRHEX       OUTPUT HEX BYTE
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    ' B='
    LDA 2,S     GET SAVED 'B'
    JSR WRHEX       OUTPUT HEX BYTE
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    ' X='
    TFR X,D     GET 'X'
    JSR WRHEXW      OUTPUT HEX WORD
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    ' Y='
    TFR Y,D     GET 'Y'
    JSR WRHEXW      OUTPUT HEX WORD
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    ' U='
    TFR U,D     GET 'U'
    JSR WRHEXW      OUTPUT HEX WORD
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    ' S='
    TFR S,D     GET 'S'
    ADDD    #7      DISCOUNT WHAT WE STACKED
    JSR WRHEXW      OUTPUT HEX WORD
    JSR LFCR        OUTPUT NEW LINE
    PULS    CC,A,B,PC   RESTORE & RETURN
*
* ZERO WORK RAM & INIT HARDWARE DEVICES
*
BEGIN   LDS #STACK      SET UP SYSTEM STACK
    ifeq    asmode,epc
    clr $1400       clear ram page
    endif
    LDX #RAM        POINT TO START OF RAM
BEG1    CLR ,X+     ZERO IT
    CMPX    #STACK      AT END?
    BLO BEG1        CONTINUE
    JSR DOINIT      INITIALIZE HARDWARE
    JSR PURGE1      INITIALIZE WORK SECTOR
    CLR >ERRCNT     INDICATE NO ERRORS
    ifne    asmode,test
* PERFORM CHECKSUM TEST OF ROM
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    'ROM... '
    LDX #ROMCHK+2   CHECKSUM STARTS HERE
    CLRA            ZERO HIGH
    CLRB            ZERO LOW
ROMT1   ADDB    ,X+     ADD IN ONE BYTE
    ADCA    #0      INSURE HIGH INCREMENTS
    CMPX    #0      AT END OF ROM?
    BNE ROMT1       NO, KEEP TRYING
    CMPD    >ROMCHK     DOES CHECKSUM MATCH?
    BEQ ROMT2       YES, ITS OK
* ROM TEST FAILED
    JSR WRMSG       OUTPUT MESSAGE
    FCCZ    'Failed'
    DEC >ERRCNT     SET FLAG, INDICATE ERROR
    BRA ROMT3
* ROM TEST PASSED
ROMT2   BSR SPASS       DISPLAY PASSED MESSAGE
    endif
* PERFORM WALKING BIT TEST OF RAM
ROMT3   JSR WRLIN       OUTPUT MESSAGE
    FCCZ    'RAM... '
    LDX >MBASE      GET BASE RAM ADDRESS
RAMT1   LDA ,X      GET ORIGINAL DATA BYTE
    LDB #%10000000  BEGIN WITH LEFTMOST BIT
RAMT2   STB ,X      WRITE TEST PATTERN
    CMPB    ,X      DOES IT MATCH
    BNE RAMT5       NO, FAILED
    LSRB            SHIFT BIT
    BNE RAMT2       DO NEXT BIT
    STA ,X+     RESTORE ORIGINAL DATA
* ON EVEN PAGE BOUNDARYS, TEST FOR ABORT KEY
    TFR X,D     GET ADDRESS
    TSTB            EVEN BOUNDARY?
    BNE RAMT3       NO, DON'T TEST
    JSR TSTCHR      ANY CHARACTERS RECEIVED?
    CMPA    #$1B        ESCAPE ABORTS?
    BEQ RAMT4       ABORT RAM TEST
* CONTINUE TILL AT END OF USER RAM
RAMT3   CMPX    #USREND     ARE WE OVER?
    BLO RAMT1       NO, ITS OK
* FINISHED, RAM TEST PASSED
    BSR SPASS       INDICATE SUCCESS
    BRA HELLO       AND PROCEED
* DISPLAY 'PASSED' MESSAGE
SPASS   JSR WRMSG       OUTPUT MESSAGE
    FCCZ    'Passed'
    RTS
* RAM TEST ABORTED BY ESCAPE
RAMT4   JSR WRMSG       OUTPUT MESSAGE
    FCCZ    'Aborted'
    BRA RAMT6       AND CONTINUE
* RAM TEST FAILED,
RAMT5   STA ,X      RESAVE OLD VALUE
    JSR WRLIN       OUTPUT FAILED MESSAGE
    FCCZ    'Failed at $'
    TFR X,D     GET ADDRESS
    JSR WRHEXW      DISPLAY IN HEX
    JSR LFCR        NEW LINE
RAMT6   DEC >ERRCNT     INDICATE ERRORS
* ISSUE HEARALD MESSAGE & START THE BALL ROLLING
HELLO   JSR WRMSG
    FCB $0A
    FCC 'CUBIX version osver'
    FCB $0A,$0D,$0A
    FCC '?COPY.TXT 1983-2005 Dave Dunfield'
    FCB $0A,$0D
    FCC '**See COPY.TXT**'
    FCB $0A,$0D,0
* IF NO ERRORS, EXECUTE THE STARTUP FILE
    LDA >ERRCNT     GET ERROR FLAG
    BNE CMD     ERRORS, DO NOT EXECUTE
    LDY #IPLFILE    POINT TO IPL FILE
    JSR GETNAM      GET FILE NAME
    LDU #CMD        ADDRESS TO RETURN TO
    PSHS    U       SAVE ON STACK (FAKE JSR)
    STS >SAVSTK     SAVE STACK INCASE ERROR
    JSR LOCDIR      LOCATE FILE IN DIRECTORY
    BNE CMD     NOT FOUND, REPORT ERROR
    JMP EXE3        EXECUTE FILE
*
* COMMAND INTERPRETER
*
CMD LDS #STACK      SET UP STACK
    JSR WRTST       WRITE OUT WORK SECTOR IF MODIFIED
    JSR GLINE       GET LINE OF INPUT
    BSR EXECMD      EXECUTE COMMAND
RCRET   BEQ CMD     NO RETURN CODE TO DISPLAY
    TFR A,B     WRITE IT
    JSR WRLIN       OUTPUT MESSAGE
    FCCZ    'Rc='
    JSR WRDEC8      OUTPUT IN DECIMAL
    JSR LFCR        NEW LINE
    BRA CMD     GET NEXT COMMAND
* RE-ENTRY POINT
REENT   PSHS    CC      SAVE CC
    LDX #0      GET A ZERO
    STX >OLDSTK     CLEAR RETURN STACK
    LDX >CMDSTK     GET CMD STACK
    BNE CMDGO       KEEP IT GOING
    PULS    CC      RESTORE CC
    BRA RCRET       AND CONTINUE
CMDGO   PULS    CC
    JMP CMDRET      RETURN TO COMMAND
* TEMPORARY DOS ENTRY
TMPENT  STS >OLDSTK     SAVE OLD STACK
DOSKCM  CLRA
    CLRB
    STD >CMDSTK     ZERO COMAND STACK
    BRA CMD     CONTINUE
*
* EXECUTE DOS COMMAND(Y)
*
EXECMD  STS >SAVSTK     SAVE STACK POINTER
    LDA >SDRIVE     GET DISK DRIVE
    STA >SAVDRV     SAVE SELECTED DRIVE
    JSR SKIP        LOOK FOR NULL COMMAND
    BEQ NULCMD      DON'T EXECUTE NULL
    STY >TEMP2      SAVED POINTER TO COMMAND
    CMPA    #'@'        EXECUTE COMMAND FILE?
    LBEQ    COMFIL      DO IT
    LDX #CMDNAM     POINT TO COMMAND TABLE
    JSR TLOOK       LOOK FOR IT
    CMPB    #NUMCMD     IS IT OVER?
    BHS EXE     YES, TRY USER DEFINED
    ASLB            TWO BYTE ENTRIES
    LDX #CMDADR     GET COMMAND ADDRESSES
    JMP [B,X]       EXECUTE COMMAND
NULCMD  RTS
*
* RUN COMMAND
*
RUN JSR GETSNA      GET FILENAME
RUN1    LDD #'EX'       GET TYPE
    STD ,X++        SAVE IT
    STA ,X      WRITE IT
    JSR LOCERR      DOES IT EXIST
* FILE HAS BEEN FOUND, EXECUTE
RUN2    LDA DATTR,X     GET ATTRIBUTES
    BITA    #EPERM      CAN WE EXECUTE?
    LBEQ    PROERR      NO, REPORT ERROR
    LDD DDADR,X     GET DISK ADDRESS
    LDX DRADR,X     GET RUN ADDRESS
    STX >TEMP1      SAVE
    JSR LCHAIN      LOAD THE CHAIN
    LDB >SDRIVE     GET OUR CURRENT DRIVE
    JSR SKIP        SKIP TO COMMANDS
    JMP [TEMP1]     PASS CONTROL TO HIM
*
* COMMAND WAS NOT RECOGNIZED, SEARCH SYSTEM DIRECTORY LOOKING
* FOR FILE WITH NAME MATCHING COMMAND.
*
EXE CLR >TEMP1      INDICATE IMPLIED RUN
    LDX #SYSDRV     PT TO SYSTEM DIRECTORY (& DRIVE)
    JSR GETDIR1     GET DIR & DRIVE
    BSR NAMGET      GET NAME
    LDA #'*'        WILDCARD
    STA ,X      SAVE TYPE
    LDA >FDRIVE     GET FILENAME DRIVE
    STA >SDRIVE     SELECT DRIVE
    LDD #DIRSEC     GET DIRECTORY SECTOR
EXE1    JSR RDWRK       READ A WORK SECTOR
EXE2    JSR COMNAM      DOES IT MATCH
    BEQ EXE3        YES, IT DOES
* NAMES DON'T MATCH, ADVANCE TO NEXT ENTRY
    LEAX    32,X        NEXT
    CMPX    #WRKSPC+512 OVER?
    BLO EXE2        NO, KEEP LOOKING
    LDD >WRKSEC     GET SECTOR
    JSR FNDLNK      LOCATE LINK
    BNE EXE1        READ IT & LOOK
* COMMAND IS INVALID, REPORT ERROR
BADCMD  LDX #UNCMD      PT TO MESSAGE
    LDA #RCCMD      GET RC
    BRA ERRMRC      REPORT ERROR
* COMMAND MATCHES FILENAME, CHECK TYPE FOR EXECUTE
EXE3    LDA DTYPE+2,X   GET TYPE
    STA >FTYPE+2    SAVE IT
    LDD DTYPE,X     GET REST OF TYPE
    STD >FTYPE      SAVE IT
* WE HAVE FOUND EXECUTABLE FILE
    CMPD    #'@'*256    IS IT A COMMAND FILE?
    LBEQ    COMGO       YES, EXECUTE
    CMPD    #'EX'       'EX'?
    BNE EXE4        NO, LOOK FOR CMD PROC
    CMPA    DTYPE+2,X   INSURE ITS 'EXE'
    BEQ RUN2        YES, EXECUTE
* UNKNOWN FILETYPE, TRY FOR USER COMMAND PROCESSOR
EXE4    TFR X,Y     'Y' POINTS TO DIR ENTRY
    LDX #FNAME      POINT TO TYPE
    STD ,X++        SAVE IT
    LDA DTYPE+2,Y   GET LAST CHR
    STA ,X+     SAVE IT
EXE5    CLR ,X+     CLEAR IT
    CMPX    #FNAME+8    OVER?
    BLO EXE5        ALL OUT
    LDY >TEMP2      RESTORE COMMAND POINTER
    JMP RUN1        TRY THIS ONE
*
* GET FILENAME WITHOUT TYPE, NORMAL DEFAULT
*
GETSNA  JSR GETDIR      GET DIRECTORY
GETSN0  LDA #$FF        FLAG
    STA >TEMP1      SET IT
NAMGET  LDB #8      MAX EIGHT CHARS
GETSN1  JSR TSTERM      TERMINATOR?
    BEQ GOPAD       YES, QUIT
    CMPA    #'/'        SPECIAL TERMINATOR
    BNE GETSN2
    LEAY    -1,Y        BACKUP TO SLASH
GOPAD   JMP PAD
GETSN2  STA ,X+     SAVE IT
    DECB            BACKUP
    BPL GETSN1      MORE
    TST >TEMP1      WERE WE 'RUN'ING
    BEQ BADCMD      NO,
*
* INVALID OPERAND
*
BADOPR  LDX #BADOPM     MESSAGE
    LDA #RCBOP      RETURN CODE
*
* ISSUE ERROR MESSAGE & RETURN TO CALLER WITH RETURN CODE
*
ERRMRC  PSHS    CC      SAVE IT
* VERIFY CONSOLE DEVICE IS VALID & RESET IF NOT
    LDB >CONOUT     GET OUTPUT
    CMPB    #NDEV       IN RANGE
    BHS ERRM1       NO - ERROR
    LDY #DOTAB      POINT TO TABLE
    ASLB            X2
    LDY B,Y     INSTALLED?
    BNE ERRM2       YES, ITS OK
ERRM1   LDB #1      DEFAULT DEVICE
    STB >CONOUT     RESET INPUT
ERRM2   LDB >CONIN      GET INPUT
    CMPB    #NDEV       IN RANGE
    BHS ERRM3       NO - ERROR
    LDY #DITAB      POINT TO TABLE
    ASLB            X2
    LDY B,Y     INSTALLED?
    BNE ERRM4       YES, ITS OK
ERRM3   LDB #1      DEFAULT DEVICE
    STB >CONIN      RESET INPUT
ERRM4   TST >MSGFLG     ARE MESSAGES ENABLED
    BEQ NOEMSG      NO, DON'T OUTPUT
    JSR WRSTR       OUTPUT
    JSR LFCR        NEW LINE
NOEMSG  PULS    CC      RESTORE CC
* RETURN TO CALLER WITH NO ERROR MESSAGE
ERRRET  PSHS    CC      SAVE CC
    LDB >SAVDRV     GET SAVED DRIVE
    STB >SDRIVE     RESET SELECTED DRIVE
    LDX >SAVX       RESTORE 'X'
    LDY >SAVY       RESTORE 'Y'
    LDB >SAVB       RESTORE 'B'
    PULS    CC      RESTORE CONDITION CODES
    BEQ ZERORC      ITS ZERO
    LDS >SAVSTK     GET SAVED SP
    RTS
ZERORC  LDS >SAVSTK     GET STACK
    ORCC    #%00000100  SET 'Z'
    RTS
*
* GET FILE WITHOUT TYPE, DEFAULT TO SYSTEM
*
GETSYS  LDX #SYSDRV     DEFAULT IS SYSTEM
*
* GET FILENAME WITHOUR TYPE, DEFAULT(X)
*
GETSDI  JSR GETDIR1     GET NAME
    JMP GETSN0      GET FILENAME
*
* COMPARES NAME(X) TO SAVED FILENAME
*
COMNAM  PSHS    A,B,X,Y     SAVE REGS
    LDY #PREFIX     POINT TO SAVED
    LDA ,X      INSURE NAME IS NOT NULL
    BNE NOTNUL      ITS NOT, 
    DECA            GET FF
    BRA CEND        QUIT
NOTNUL  LDB #8      EIGHT CHARS NI PREFIX
    BSR COMX        COMPARE
    BNE CEND        NOT SAME, EXIT
    LDB #8      EIGHT CHARS IN NAME
    BSR COMX        COMPARE
    BNE CEND        NOT SAME
    LDB #3      THREE CHARS IN TYPE
    BSR COMX        COMPARE
CEND    PULS    A,B,X,Y,PC  GO HOME
COMX    LDA ,Y+     GET CHAR FROM SAVED
    CMPA    #'*'        WILDCARD?
    BEQ RNXT        RETURN WITH TRUE
    CMPA    ,X+     DOES IT MATCH
    BNE RNXT1       NO, FAIL
    DECB            BACKUP
    BNE COMX        OK
    RTS
RNXT    LEAX    1,X
RNXT1   DECB            REDUCE COUNT
    BEQ BRET        DONE, QUIT
    LEAY    1,Y     ADVANCE
    BRA RNXT        AND CONTINUE
BRET    CMPA    #'*'        WUZ IT WILDCARD
    RTS
*
* TEST SAVED FILENAME FOR VALIDITY AS A SINGLE FILE
*
VALID   PSHS    A,B,X       SAVE REGS
    LDB #19     LENGTH OF NAME
    LDX #PREFIX     POINT TO NAME
VALTST  LDA ,X+     GETCHAR
    CMPA    #'*'        WILDCARD
    BEQ RETNZ       INVALID
    DECB            BACKUP
    BNE VALTST      CONTINUE
    CLRA            ZERO RETURN CODE
RETNZ   TSTA            SET 'Z' FLAG
    PULS    A,B,X,PC
*
* GET FILENAME & INSURE ITS VALID
*
GETVAL  BSR GETNAM      GET FILENAME
    BSR VALID       TEST FOR VALID
    BNE BADOP2      INVALID, ERROR
    RTS
*
* GET A FILENAME FROM INPUT LINE
*
GETNAM  BSR GETDIR      GET DRIVE & DIRECTORY
GFNAM   LDB #8      EIGHT CHARS/NAME
GF1 BSR VALCHR      GET CHAR
    CMPA    #'.'        SEPERATOR?
    BEQ GFTYP       YES
    STA ,X+     SAVE IT
    DECB            BACKUP
    BPL GF1     KEEP GOING
    BRA BADOP2      ERROR
GFTYP   BSR PAD     PAD FILENAME
    LDB #3      THREE CHARS/TYPE
GF2 JSR TSTERM      GET CHAR
    BEQ GF3     HIT END
    STA ,X+     SAVE IT
    DECB            REDUCE COUNT
    BPL GF2     KEEP GOING
BADOP2  JMP BADOPR      ERROR
GF3 BSR PAD     ZERO IT
    JSR SKIP        TO NEXT
    LDX #PREFIX     POINT TO IT
    CLRA            ZERO RC
    RTS
* ABORT IF CHARACTER INVALID
VALCHR  JSR TSTERM      TEST FOR CHAR OK
    BEQ BADOP2      INVALID
    RTS
* PADS NAME WITH BLANKS UNTILL 'B' IS ZERO
PAD DECB            BACKUP COUNT
    BMI GETD5       THATS ALL
    CLR ,X+     CLEAR IT
    BRA PAD
*
* GETS A DRIVE AND DIRECTORY FROM THE INPUT LINE
*
GETDIR  LDX #DEFDRV     PT TO IT
GETDIR1 LDA ,X+     GET DEFAULT DRIVE
    STA >FDRIVE     SET IT
    JSR SKIP        ADVANCE
    BEQ GETD1       END OF LINE, NO DRIVE SPEC
    LDB 1,Y     GET NEXT CHAR
    CMPB    #':'        IS IT A DRIVE SPEC?
    BNE GETD1       NO, IGNORE IT
    BSR GETDRV1     GET DRIVE ID
    STA >FDRIVE     SET DRIVE ID
GETD1   PSHS    Y       SAVE
    TFR X,Y     SET UP PTR TO DEFAULT
    LDX #PREFIX     POINT TO PREFIX
    LDB #8      MOVE EIGHT
GETD2   LDA ,Y+     GET FROM DEFAULT
    STA ,X+     SAVE IN NAME
    DECB            REDUCE COUNT
    BNE GETD2       MOVE EM ALL
    PULS    Y       RESTORE
    LDA ,Y      GET CHAR
    CMPA    #'['        DIRECTORY ID
    BNE GETD5       NO, SKIP IT
    LDX #PREFIX     POINT TO PREFIX
    LEAY    1,Y     ADVANCE
    LDB #8      UP TO EIGHT CHARS
GETD3   JSR VALCHR      GET CHAR, INSURE VALID
    CMPA    #']'        CLOSING?
    BEQ GETD4       YES
    STA ,X+     SAVE IT
    DECB            BACKUP
    BPL GETD3       KEEP GOING
BADOP1  JMP BADOPR
GETD4   BSR PAD     PAD WITH BLANKS
    TST >PREFIX     IS IT NULL
    BEQ BADOP1      INVALID
GETD5   CLRA
    RTS
* GET A DRIVE & RETURN IN A
GETDRV  JSR SKIP        ADVANCE TO OPERAND
GETDRV1 LDD ,Y++        GET DATA
    CMPB    #':'        COLON
    BNE BADOP1      NO
    SUBA    #'A'        CONVERT
    CMPA    #4      IN RANGE
    BHS BADOP1      NO
    ORCC    #4      SET 'Z'
    RTS
*
* GETS A VALUE (DECIMAL OR HEX) FROM INPUT LINE
*
GETNUM  JSR SKIP        SKIP TO DATA
    BEQ BADOP1      INVALID
    CMPA    #'$'        HEX?
    BNE GETDV       NO, GET DECIMAL
    LEAY    1,Y     ADVANCE TO NEXT
*
* GETS A 16 BIT HEX NUMBER FOR X FROM THE INPUT LINE.
*
GETHEX  JSR SKIP        GET CHARACTER
    BEQ BADOP1      INDICATE BAD OPERAND
GETHV   LDX #0      START WITH ZERO
GETL1   JSR TSTERM      TEST FOR TERMINATOR
    BEQ HEXEND      IF SO, THIS IS IT
    SUBA    #'0'        CONVERT TO BINARY
    CMPA    #10     TEST FOR > '9'
    BLO DIGOK       IF NOT, DIGIT IS OK
    CMPA    #$11        TEST FOR < 'A'
    BLT BADOP1      OPERAND IS INVALID
    SUBA    #7      CONVERT TO ASCII
    CMPA    #$10        TEST FOR 0-F
    BHS BADOP1      IF NOT, DIGIT IS BAD
DIGOK   STA >TEMP+1     SAVE FOR LATER
    LDA #5      SHIFT FOUR TIMES
    STA >TEMP       SAVE COUNTER
DSHFT   TFR X,D     COPY TO X
    LEAX    D,X     MULTIPLY BY 2, = 1 BIT SHIFT
    DEC >TEMP       REDUCE COUNT
    BNE DSHFT       KEEP SHIFTING
    ORB >TEMP+1     STICK ON EXTRA DIGIT
    TFR D,X     COPY BACK TO X
    BRA GETL1       GET NEXT DIGIT
HEXEND  JSR SKIP        ADVANCE TO NEXT OPERAND
    CLRA            INDICATE ZERO RETURN CODE
    RTS
*
* GETS A DECIMAL NUMBER FROM THE TERMINAL.
*
GETDEC  JSR SKIP        SKIP TO START OF OPERAND.
    LBEQ    BADOPR      IF INVALID, GO BACK.
GETDV   LDX #0      START WITH ZERO.
DECDIG  JSR TSTERM      TEST FOR TERMINATOR
    BEQ HEXEND      IF THATS ALL, FORGET IT.
    SUBA    #'0'        CONVERT TO BINARY.
    CMPA    #9      TEST FOR INVALID.
    LBHI    BADOPR      AGAIN, INVALID OPERAND.
    PSHS    A       SAVE ACC.
    LDD #10     MUL BY 10
    JSR MUL16       D=D*X
    ADDB    ,S+     ADD IN DIGIT
    ADCA    #0      INSURE HIGH GOES
    TFR D,X     COPY TO RESULT
    BRA DECDIG      GET NEXT
*
WRDEC8  CLRA            DISPLAY 8 BIT BUMBER (B) IN DECIMAL
*
* DISPLAYS 16 BIT NUMBER IN D AS A DECIMAL NUMBER,
*
WRDEC   PSHS    A,B,X,Y     SAVE X-Y REGISTERS
    LDY #0      START WITH ZERO CHARACTERS
    TFR D,X     SET UP STARTING VALUE
WRDE1   LDD #10     DIVIDE BY 10
    JSR DIV16       X=X/D, D=REMAINDER
    PSHS    B       SAVE REMAINDER
    LEAY    1,Y     INDICATE ANOTHER ON STACK
    CMPX    #0      ANY MORE?
    BNE WRDE1       NO, CONTINUE
WRDE2   PULS    A       GET DIGIT BACK
    ADDA    #'0'        CONVERT TO PRINTABLE FORM
    JSR PUTCHR      DISPLAY DECIMAL DIGIT
    LEAY    -1,Y        REDUCE COUNT
    BNE WRDE2       IF NOT END, CONTINUE DISPLAYING
    PULS    A,B,X,Y,PC  RESTORE INDEX REG'S
*
* GETS AND BUFFERS A LINE FROM THE TERMINAL, ON EXIT, Y REGISTER
* POINTS TO LINE IN BUFFER.
*
GLFCR   JSR LFCR        START A NEW LINE
GLINE   LDA #'*'        GET PROMPT CHARACTER
    JSR PUTCHR      DISPLAY
GLNOP   LDY #INBUFF     POINT TO INPUT BUFFER
GLINE1  TFR Y,D     GET POINTER INTO BUFFER
    CMPB    #80     TEST FOR OVER LIMIT
    BHI GLFCR       INDICATE ERROR
    JSR GETCHR      GET CHARACTER FROM CONSOLE
    CMPA    #$7F        TEST FOR DELETE
    BEQ GLINE2      YES, PERFORM DELETE
    CMPA    #8      TEST FOR BACKSPACE
    BNE GLINE3      DON'T DELETE
GLINE2  LEAY    -1,Y        DELETE A CHARACTER
    JSR WRLIN       OUTPUT MESSAGE
    FCB 8,' ',8,0   WIPE PREVIOUS CHARACTER
    BRA GLINE1      GET NEXT CHARACTER
GLINE3  JSR PUTCHR      ECHO CHARACTER
    BSR TOUPPER     CONVERT TO UPPERCASE
    STA ,Y+     SAVE IN BUFFER
    CMPA    #$0D        TEST FOR END OF LINE
    BNE GLINE1      GET NEXT CHARACTER
    LDY #INBUFF     POINT TO BUFFER
    JMP LFCR        START A NEW LINE
*
* SKIPS TO NEXT NON-BLANK CHARACTER IN INPUT LINE. AND TESTS IT FOR <CR>.
*
SKIP    LDA ,Y+     GET CHARACTER
    CMPA    #' '        TEST FOR BLANK
    BEQ SKIP        IF SO, KEEP LOOKING
    TST ,-Y     BACKUP & TEST FOR ZERO
    BEQ SKRTS       YES, END WITH 'Z' SET
    CMPA    #$0D        TEST FOR CARRIAGE RETURN
SKRTS   RTS
*
* TESTS FOR VALID TERMINATOR CHARACTERS.
*
TSTERM  LDA ,Y+     GET CHARACTER AND ADVANCE
    BEQ TSTE1       IF NULL, INDICATE TERMINATOR
    CMPA    #' '        TEST FOR SPACE
    BEQ TRET        IF SO, QUIT
    CMPA    #$0D        IS IT A CARRIAGE RETURN
    BNE TRET        IF NOT, DON'T BACK UP
TSTE1   LEAY    -1,Y        BACK UP SO WE DON'T GO BEYOND
    ORCC    #%00000100  SET 'Z'
TRET    RTS
*
* CONVERT THE CHARACTER IN 'A' TO UPPER CASE
*
TOUPPER CMPA    #'A'+$20    ALREADY UPPERCASE?
    BLO TRET        YES, ITS OK
    CMPA    #'Z'+$20    ALREADY UPPERCASE?
    BHI TRET        YES, ITS OK
    ANDA    #%01011111  CONVERT TO UPPERCASE
    RTS
*
* LOOKS UP WORD(Y) IN TABLE(X). INDEX OF COMMAND IN TABLE IS
* RETURNED IN THE B REGISTER, WITH ZERO BEING THE FIRST COMMAND.
* FOR INFORMATION ON THE COMMAND TABLE FORMAT, SEE COMMAND TABLE.
*
TLOOK   CLRB            START WITH ZERO ENTRY
    BSR SKIP        SKIP LEADING BLANKS
TLOOK1  LDA ,X+     GET CHAR FROM FILE
    BPL TLOOK1      ADVANCE TO CONTROL BYTE
    LEAX    -1,X        BACKUP TO IT
    PSHS    Y       SAVE POSITION
    ANDA    #$7F        REMOVE FLAG BIT
    BEQ TLOOK6      END OF TABLE ENCOUNTERED
    STA >TEMP       SAVE FOR LATER REF
TLOOK2  LEAX    1,X     ADVANCE IN TABLE
    DEC >TEMP       REDUCE COUNT
    LDA ,X      GET CHAR
    BSR TOUPPER     CONVERT TO UPPERCASE
    STA >TEMP+1     SAVE FOR LATER
    BSR TSTERM      TEST FOR TERMINATOR
    BEQ TLOOK5      IF SO, TEST IT
    CMPA    >TEMP+1     TEST FOR SAME AS TABLE ENTRY
    BEQ TLOOK2      IF SO, IT'S OK
    CMPA    #'/'        SLASH?
    BEQ TLOOK4      YES, ACCEPT IT
    CMPA    #'='        EQUALS?
    BEQ TLOOK4      ACCEPT IT AS WELL
* THIS ENTRY NOT FOUND, SKIP TO NEXT ONE
TLOOK3  PULS    Y       RESTORE COMMAND POINTER
    INCB            INC. INDICATOR
    BRA TLOOK1      TRY NEXT ENTRY
TLOOK4  LEAY    -1,Y        BACKUP TO SPECIAL CHAR
TLOOK5  ORA >TEMP       TEST FOR MINIMUM NUMBER OF CHARS
    BPL TLOOK3      IF NOT, SKIP THIS COMMAND
TLOOK6  BSR SKIP        SKIP TO OPERANDS
    TSTB            SET FLAG IS ZERO
    PULS    X,PC        CLEAN UP STACK
*
* OUTPUT NUMBER IN 'D' TO CONSOLE IN HEX
*
WRHEXW  BSR WRHEX       OUTPUT
    EXG A,B     SWAP
    BSR WRHEX       OUTPUT
    EXG A,B     BACK
    RTS
*
* WRITE MESSAGE, NO CARRIAGE RETURN AT END
*
WRLIN   PSHS    X       SAVE X
    LDX 2,S     GET ADDRESS BACK
    BSR WRSTR       OUTPUT
    STX 2,S     RESAVE
    ORCC    #%00000100  ZERO RETURN CODE
    PULS    X,PC
*
* OUTPUT 'A' NUMBER TO CONSOLE IN HEX
*
WRHEX   PSHS    A       SAVE IT
    LSRA            SHIFT
    LSRA            HIGH NIBBLE
    LSRA            INTO
    LSRA            LOW NIBBLE
    BSR HOUT        HIGH
    LDA ,S      GET LOW
    BSR HOUT        OUTPUT
    PULS    A,PC        RESTORE IT
* OUTPUT NIBBLE IN HEX
HOUT    ANDA    #%00001111  REMOVE HIGH
    ADDA    #'0'        CONVERT
    CMPA    #'9'        OK?
    BLS PUTCHR      OK, OUTPUT
    ADDA    #7      CONVERT TO 'A'-'F'
    BRA PUTCHR      OUTPUT
*
* WRITE STRING(X) TO CONSOLE
*
WRSTR   PSHS    A       SAVE A
WRST1   LDA ,X+     GET CHAR
    BEQ WRST2       END, QUIT
    BSR PUTCHR      OUTPUT
    BRA WRST1       CONTINUE
*
* OUTPUT MESSAGE TO CONSOLE
*
WRMSG   PSHS    X       SAVE X
    LDX 2,S     GET RETURN ADDRESS
    BSR WRSTR       OUTPUT STRING
    STX 2,S     RESAVE NEW RETURN ADDR
    PULS    X       RESTORE X
*
* OUTPUT LFCR TO CONSOLE
*
LFCR    PSHS    A       SAVE IT
    LDA #$0A        GET LF
    BSR PUTCHR      OUTPUT
    LDA #$0D        GET CR
    BRA SPC1        CONTINUE
*
* OUTPUT SPACE TO CONSOLE
*
SPACE   PSHS    A       SAVE ACCA
    LDA #' '        GET SPACE
SPC1    BSR PUTCHR      OUTPUT
WRST2   PULS    A,PC        RESTORE
*
* WRITE CHARACTER(A) TO CONSOLE DEVICE
*
PUTCHR  PSHS    A,B,X       SAVE REGS
    LDB >CONOUT     GET CONSOLE OUTPUT DEVICE
    BRA WRDEV1      PROCEDE WITH OUTPUT
*
* WRITE CHARACTER(A) TO DEVICE(B)
*
WRDEV   PSHS    A,B,X       SAVE REGS
WRDEV1  CMPB    #NDEV       CHECK FOR IN RANGE
    BHS BADDEV      INDICATE INVALID
    LDX #DOTAB      POINT TO STATUS TABLE
    ASLB            X2 FOR TWO BYTE ENTRIES
    LDX B,X     GET DEVICE DRIVER ADDRESS
    BEQ BADDEV      INDICATE INVALID DEVICE
    JSR ,X      EXECUTE OUTPUT DRIVER
    CLRA            ZERO RETURN CODE
    PULS    A,B,X,PC    RESTORE & RETURN
*
* BAD DEVICE SPECIFIED
*
BADDEV  LDX #DEVMSG     POINT TO DEVICE MESSAGE
    LDA #RCDEV      BAD DEVICE RETURN CODE
    JMP ERRMRC      EXIT WITH ERROR
*
* READ A CHARACTER FROM DEVICE (B)
*
RDDEV   BSR TSTDEV      TEST FOR CHAR
    BNE RDDEV       WAIT FOR IT
    RTS
*
* TEST FOR CHARACTER FROM DEVICE(B)
*
TSTDEV  PSHS    B,X     SAVE REGS
TSTDE1  CMPB    #NDEV       DEVICE IN RANGE?
    BHS BADDEV      INDICATE INVALUD
    LDX #DITAB      POINT TO STATUS TABLE
    ASLB            X2 FOR TWO BYTE ENTRIES
    LDX B,X     GET DEVICE DRIVER ADDRESS
    BEQ BADDEV      INDICATE INVALID
    JSR ,X      EXECUTE INPUT DRIVER
    PULS    B,X,PC      RESTORE & RETURN
*
* TEST FOR A CHARACTER FROM THE CONSOLE DEVICE
*
TSTCHR  PSHS    B,X     SAVE REGS
    LDB >CONIN      GET INPUT DEVICE
    BRA TSTDE1      AND CONTINUE
*
* READ A CHARACTER FROM CONSOLE
*
GETCHR  BSR TSTCHR      TEST FOR CHAR
    BNE GETCHR      INDICATE NONE
    RTS
*
* INCLUDE ALL OTHER SUB-SYSTEMS
*
    include filesys.os  FILE SYSTEM MANAGMENT
    include command.os  INTERNAL COMMANDS
    include comfile.os  BATCH FILE PROCESSOR
*
* MISC SYSTEM CALLS
*
* QUERY CONSOLE INPUT DEVICE
REDIN   LDA >CONIN      LOAD DEVICE INPUT VECTOR
    BRA RETZ        RETURN SUCCESS
* QUERY CONSOLE OUTPUT DEVICE
REDOUT  LDA >CONOUT     LOAD DEVICE OUTPUT VECTOR
    BRA RETZ        RETURN SUCCESS
* SET CONSOLE INPUT DEVICE
SETIN   PSHS    B       SAVE REGISTER
    LDB >CONIN      LOAD OLD INPUT DEVICE
    STA >CONIN      SAVE NEW INPUT DEVICE
    BRA REEXG       SWAP & RETURN
* SET CONSOLE OUTPUT DEVICE
SETOUT  PSHS    B       SAVE REGISTER
    LDB >CONOUT     LOAD OLD OUTPUT DEVICE
    STA >CONOUT     SAVE NEW OUTPUT DEVICE
REEXG   TFR B,A     COPY OLD DEVICE ID TO 'A'
    ORCC    #4      SET 'Z' CODE
    PULS    B,PC        RESTORE & RETURN
* SELECT DISK DRIVE
SELDRV  STA >SDRIVE     SELECT ACTIVE DISK DRIVE
RETZ    ORCC    #4      SET 'Z' CODE
    RTS
* QUERY DEVICE VECTOR
QVECT   PSHS    U       SAVE REGISTER
    LDU #DITAB      POINT TO TABLE
    LSLA            X2 FOR WORD ENTRIES
    LDD A,U     GET VECTOR
    BRA RETZ1       AND EXIT
* SET DEVICE VECTOR
SVECT   PSHS    U       SAVE REGISTER
    LDU #DITAB      POINT TO TABLE
    LSLA            X2  FOR WORD ENTRIES
    LEAU    A,U     OFFSET TO ENTRY
    LDD ,U      GET OLD VECTOR VALUE
    STX ,U      SET NEW VECTOR VALUE
RETZ1   ORCC    #4      SET 'Z' CODE
    PULS    U,PC        RESTORE & RETURN
*
* PERFORMS 16 BIT MULTIPLICATION (D=X*D)
*
MUL16   PSHS    D,X     SAVE PARAMETERS
    LDA 1,S
    LDB 3,S
    MUL
    PSHS    A,B     RESAVE
    LDA 2,S
    LDB 5,S
    MUL
    ADDB    ,S
    STB ,S
    LDA 3,S
    LDB 4,S
    MUL
    ADDB    ,S
    STB ,S
    PULS    A,B     GET RESULT
    LEAS    4,S     SKIP CRAP
    RTS
*
* PERFORMS 16 BIT DIVISION. (X=X/D, D=REMAINDER)
*
DIV16   PSHS    D,X
    LDD #0
    LDX #17
DIV1    ANDCC   #$FE
DIV2    ROL 3,S
    ROL 2,S
    LEAX    -1,X
    BEQ DIV3
    ROLB
    ROLA
    CMPD    ,S
    BLO DIV1
    SUBD    ,S
    ORCC    #1
    BRA DIV2
DIV3    LEAS    2,S
    PULS    X,PC
* DISK DRIVERS
FORMAT  JSR [XFORMAT]
HOME    CLR CYL,U       CYLINDER 0
    CLR HEAD,U      HEAD 0
    CLR SEC,U       SECTOR 0
    JMP [XHOME]
RDSEC   JMP [XRDSEC]
WRSEC   JMP [XWRSEC]
* INTERRUPT HANDLERS
SWI JMP [SWIVEC]
SWI2    JMP [SWI2VEC]
SWI3    JMP [SWI3VEC]
IRQ JMP [IRQVEC]
FIRQ    JMP [FIRQVEC]
NMI JMP [NMIVEC]
* STRINGS & MESSAGES
IPLFILE FCCZ    'STARTUP.*'
UNCMD   FCCZ    'Unrecognized command'
BADOPM  FCCZ    'Operand missing or invalid'
NOTMSG  FCCZ    'File not found'
EXIMSG  FCCZ    'File already exists'
NOSMSG  FCCZ    'Insufficent disk space'
OREMSG  FCCZ    'File not open for read'
OWEMSG  FCCZ    'File not open for write'
PROMSG  FCCZ    'File protection violation'
DEVMSG  FCCZ    'Invalid device'
DNLMSG  FCCZ    'Download format error'
* COMMAND NAME TABLE
CMDNAM  FCB $84
    FCC 'FORMAT'
    FCB $82
    FCC 'READ'
    FCB $82
    FCC 'WRITE'
    FCB $82
    FCC 'FILES'
    FCB $82
    FCC 'CREATE'
    FCB $83
    FCC 'DELETE'
    FCB $82
    FCC 'LOAD'
    FCB $82
    FCC 'SAVE'
    FCB $82
    FCC 'RUN'
    FCB $82
    FCC 'RETURN'
    FCB $82
    FCC 'SET'
    FCB $82
    FCC 'SHOW'
    FCB $82
    FCC 'DOWNLOAD'
    FCB $82
    FCC 'CONNECT'
    FCB $80
* COMMAND ADDRESS TABLE
CMDADR  FDB INIT
    FDB CREAD
    FDB CWRITE
    FDB FILES
    FDB CREFIL
    FDB DELFIL
    FDB LODFIL
    FDB SAVFIL
    FDB RUN
    FDB RETURN
    FDB SET
    FDB SHOW
    FDB DNLD
    FDB CNCT
NUMCMD  EQU *-CMDADR/2  NUMBER OF COMMANDS
* APPLICATION PROGRAM INTERFACE ADDRESS TABLE
SSRTAB  FDB REENT       00-DOS RE-ENTRY
* PARAM. & LINE INPUT
    FDB GLINE       01-GET LINE/PROMPT
    FDB GLFCR       02-GET LINE/NEW LINE
    FDB GLNOP       03-GET LINE/NO PROMPT
    FDB SKIP        04-SKIP TO NEXT NON-BLANK, 'Z' IF EOL
    FDB TSTERM      05-GET CHR(Y+), TEST FOR TERMINATOR
    FDB GETDEC      06-GET DECIMAL NUMBER
    FDB GETHEX      07-GET HEX NUMBER
    FDB GETNUM      08-GET DECIMAL OR HEX VALUE
    FDB GETNAM      09-GET FILENAME
    FDB GETVAL      10-GET & INSURE SINGLE FILE
    FDB GETSNA      11-GET FILENAME/NO TYPE
    FDB GETSYS      12-GET FILENAME/NO TYPE/DEFAULT SYSTEM
    FDB GETSDI      13-GET FILENAME/NO TYPE/DEFAULT(X)
    FDB GETDIR      14-GET DIRECTORY NAME
    FDB GETDIR1     15-GET DIRECTORY, DEFAULT(X)
    FDB GETDRV      16-GET DRIVE ID
    FDB GETATR      17-GET ATTRIBUTES
    FDB TLOOK       18-TABLE LOOKUP
    FDB COMNAM      19-COMPARE NAMES
    FDB VALID       20-TEST FOR VALID AS SINGLE?
* CONSOLE OUTPUT
    FDB SPACE       21-OUTPUT SPACE
    FDB LFCR        22-OUTPUT LFCR
    FDB WRSTR       23-OUTPUT STRING(X)
    FDB WRLIN       24-OUTPUT STRING(PC)/NO LFCR
    FDB WRMSG       25-OUTPUT STRING(PC)/LFCR
    FDB WRDEC       26-OUTPUT WORD(D) DECIMAL
    FDB WRHEXW      27-OUTPUT WORD(D) IN HEX
    FDB WRHEX       28-OUTPUT BYTE(A) IN HEX
    FDB HOUT        29-OUTPUT NIBBLE(A) IN HEX
    FDB SHOSAV      30-DISPLAY SAVED FILENAME
    FDB SHONAM      31-DISPLAY FILENAME(X)
    FDB SHOTAB      32-SHOW TABLE(X) ENTRY(A)
* SERIAL DEVICE I/O
    FDB PUTCHR      33-OUTPUT CHAR(A)
    FDB GETCHR      34-GET A CHAR
    FDB TSTCHR      35-TEST FOR CHAR
    FDB WRDEV       36-OUTPUT CHAR(A) TO DEVICE(B)
    FDB RDDEV       37-GET CHAR FROM DEVICE(B)
    FDB TSTDEV      38-TEST FOR CHAR FROM DEV(B)
    FDB REDIN       39-READ INPUT DEVICE NUMBER
    FDB REDOUT      40-READ OUTPUT DEVICE NUMBER
    FDB SETIN       41-SET INPUT DEVICE
    FDB SETOUT      42-SET OUTPUT DEVICE
* CANNED ERROR MESSAGES
    FDB BADOPR      43-OPERAND MISSING OR INVALID
    FDB NOTFND      44-FILE NOT FOUND
    FDB PROERR      45-PROTECTION VIOLATION
    FDB ORERR       46-FILE NOT OPEN FOR READ
    FDB OWERR       47-FILE NOT OPEN FOR WRITE
    FDB FEXISTS     48-FILE ALREADY EXISTS
    FDB NOSPAC      49-INSUFFICENT DISK SPACE
    FDB BADDEV      50-INVALID DEVICE
    FDB LODERR      51-DOWNLOAD FORMAT ERROR
    FDB FILERR      52-ISSUE ERROR MSG(Y) FOR SAVED FILE
* FILE I/O
    FDB BLOAD       53-LOAD COMPLETE FILE TO MEMORY
    FDB BSAVE       54-SAVE COMPLETE FILE FROM MEMORY
    FDB OPENR       55-OPEN A FILE FOR READ
    FDB OPENW       56-OPEN A FILE FOR WRITE
    FDB CLOSE       57-CLOSE A FILE
    FDB READB       58-READ BLOCK FROM FILE
    FDB READC       59-READ CHAR FROM FILE
    FDB WRITEB      60-WRITE A BLOCK TO FILE
    FDB WRITEC      61-WRITE A CHAR TO FILE
    FDB REWIND      62-RESET FILE TO BEGINNING
    FDB SEEKREL     63-SEEK RELATIVE POSITION IN FILE
    FDB SEEKABS     64-SEEK ABSOLUTE LOCATION IN FILE
    FDB FTELL       65-RETURN POSITION IN FILE
    FDB SUSPEND     66-SUSPEND FILE OPERATIONS
    FDB RESUME      67-RESUME FILE OPERATIONS
* FILE SYSTEM MAINTAINENCE
    FDB LOCDIR      68-LOCATE FILE IN DIRECTORY, NO ERROR/MESSAGE
    FDB LOCERR      69-LOCATE FILE IN DIR/ISSUE ERROR IF NOT FOUND
    FDB LOCRED      70-LOCATE FILE WITH INTENT TO READ
    FDB LOCWRI      71-LOCATE FILE WITH INTENT TO WRITE
    FDB CREATE      72-CREATE A FILE
    FDB DELETE      73-DELETE A FILE
    FDB SETDEF      74-SET DEFAULT DIRECTORY
    FDB SETCMD      75-SET COMMAND DIRECTORY
    FDB SELDRV      76-SET CURRENT OS DRIVE
    FDB FNDLNK      77-LOCATE LINK FOR SECTOR
    FDB LCHAIN      78-LOAD CHAIN OF SECTOR TO MEMORY
    FDB FRESEC      79-ALLOCATE A FREE SECTOR
    FDB UNCHAIN     80-RELEASE SECTOR CHAIN
    FDB DRVSIZ      81-CALCULATE SIZE OF DISK(A)
    FDB CURSIZ      82-CALCULATE SIZE OF CURRENT DISK
    FDB CALFRE      83-CALCULATE # FREE SECTORS ON DISK
    FDB RDWRK       84-READ WORK SECTOR INTO DOS
    FDB CHGWRK      85-INDICATE WORK SECTOR CHANGED
    FDB WRTST       86-WRITE WORK SECTOR IF UPDATED
    FDB WRWRK       87-WRITE WORK SECTOR UNCONDITIONALLY
    FDB PURGE       88-CLEAR WORK SECTOR & FORCE READ
    FDB GETCTL1     89-GET CONTROL BLOCK
    FDB GETCTL      90-GET CTRL BLK FOR SELECTED
    FDB SECTOR      91-SET UP CTRL-BLOCK FROM DISK ID
    FDB RDISK       92-READ SECTOR(D) TO MEM(X) FROM DISK
    FDB WDISK       93-WRITE SECTOR(D) FROM MEM(X) TO DISK
    FDB DISDIR      94-DISPLAY DISK DIRECTORY
* DIRECT DISK ACCESS
    FDB DOINIT      95-INIT HARDWARE
    FDB HOME        96-HOME HEAD ON DISK
    FDB RDSEC       97-READ SECTOR FROM TRACK
    FDB WRSEC       98-WRITE SECTOR FROM TRACK
    FDB FORMAT      99-FORMAT DISK
* MISC DOS ROUTINES
    FDB EXECMD      100-EXECUTE DOS COMMAND
    FDB TMPENT      101-TEMPORARY DOS ENTRY
    FDB QVECT       102-QUERY DEVICE VECTOR
    FDB SVECT       103-SET DEVICE VECTOR
    FDB SETFLG      104-SET FLAG
    FDB CLRFLG      105-CLEAR FLAG
    FDB SAVPRM      106-SET COMMAND FILE PARAMETERS
    FDB MUL16       107-16 BIT MULTIPLY (D=X*D)
    FDB DIV16       108-16 BIT DIVISION (X=X/D, D=REMAINDER)
    FDB DMPREG      109-DISPLAY REGISTERS
    FDB DNLDEV      110-DOWNLOAD FROM DEVICE
NUMSSR  EQU *-SSRTAB/2  # SSR'S IMPLEMENTED
*
* HARDWARE DEPENDANT I/O DRIVERS
*
    ifeq    asmode,dist
HWINIT  EQU *       ADDRESS OF HW INIT ROUTINE
    else
    include dr_file
    endif
*
* INTERRUPT VECTORS
*
    ifne    asmode,test
    ORG $FFF2       VECTORS GO HERE
    FDB SWI3
    FDB SWI2
    FDB FIRQ
    FDB IRQ
    FDB SWI
    FDB NMI
    FDB BEGIN       RESET - COLD START OF SYSTEM
    endif
