Skip to content

Instantly share code, notes, and snippets.

@claus
Created April 2, 2016 01:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save claus/118a26c6bef7ae6ebe338797b074a7e1 to your computer and use it in GitHub Desktop.
Save claus/118a26c6bef7ae6ebe338797b074a7e1 to your computer and use it in GitHub Desktop.
;
; Apple DOS 3.1 Disassembly - (Patched Release - RAWDOS)
;
; This disassembly is based on the original pre-release Apple DOS source
; code written in 1978 by Paul Laughton, then an employee of Shepardson
; Microsystems. The source document is identified on the title page with
; the following text:
;
; .TITLE SHEP,'APPLE DOS'
; 6.3 10-6-78
; 8 BIT ASSEMBLER
; .M6502
;
; The binary produced by assembling this source has been compared to
; the RAWDOS binary included on the Apple DOS 3.1 Master Disk and was
; was found to be identical with one exception:
;
; Assembling this source code into a binary will generally initialize
; reserved memory byte (RMB) address spaces as well as any unused address
; space (addresses located between the end of a given section of code and
; a new ORG directive) to 0x00 or 0xff, depending on the assembler used.
;
; Accordingly, all comparisons to the original DOS 3.1 binary insured
; that the only differences were with byte values that were located in
; unused address locations or in RMB address locations.
;
;
; Scott LaBombard
; labomb@rochester.rr.com
; 12/04/2013
;
#INCLUDE "MOTO.H"
.TITLE "APPLE DOS 3.1"
*
**************************************************************************************
* (C) COPYRIGHT 1978 APPLE COMPUTER, INC
**************************************************************************************
ORG1 EQU $1B00
ORG2 EQU $3600
DISKIO EQU $3D00
ASC1 EQU $3800
AEC1 EQU $3A8F
ASC2 EQU $3D00
AEC2 EQU $3FFF
EDOS EQU $4000
PAGE
ORG ORG1
BEGIN 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
DR1B
LDY #0 ;APPLE TEST
LDA (ZPGWRK,X)
STA LOC1
DR1 TYA
EOR LOC1
STA LOC1
TYA
EOR (ZPGWRK,X)
STA (ZPGWRK,X)
CMP LOC1
BNE DR1A
INY
BNE DR1
BEQ DR2 ; BR IF TOOK
DR1A
DEC !ZPGWRK+1 ; NOT RAM
BNE DR1B ; TRY NEXT PAGE
;
DR2
;
JSR DR2PAT ; *** PATCH ***
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 BEGIN ; (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 ; THEN IGNORE
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 STARTT/256
INSDS2 EQU $F88E
LENGTH EQU $2F
ADRTAB DB 9*4
DW @@SAT1,@@EAT1
DW @@RUN,@@RUN+2
DW @@IBVT+2,@@IBVT+4
DW @@AS1VT,@@AS1VT+4
DW @@AS2VT,@@AS2VT+4
DW @@AS2VT+6,@@AS2VT+8
DW @@SAT2,@@EAT2
DW @@BAIOB,@@ADOSLD+2
DW @@IBDCTP,@@IBDCTP+2
DW @0,@0
DW @0,@0
DW @0,@0
CDETAB
DB 6*4
DW @@SC1,@@EC1
DW @@SC2,@@EC2
DW @@SC3,@@EC3
DW @@SDP1,@@EDP1
DW @@ASC1,@@AEC1
DW @@ASC2,@@AEC2
DW @0,@0
;
RSPAGE DB DSPAGE
REPAGE DB DEPAGE
;
NSPAGE DB 0
NEPAGE DB 0
;
DOSLNG DB DEPAGE-DSPAGE
;
DELTA DB 0
DPGCNT DB DEPAGE-DSPAGE
PAGE
BOUND 256
;
; RELOCATION TABLES
;
START
SAT1
FTAB DW @@*-45 ;START OF FTABS
CINA DW @@CHRIN ;CHAR IN ADR
COUTA DW @@CHROUT ;CHAR OUT ADR
FN1ADR DW @@FNAME1
FN2ADR DW @@FNAME2
SVBLA DW @@SVBL
ASTART DW @@BEGIN ; CHANGED TO START BY RELOCATE
CCBADR DW @@CCB
;
OUTSVT ;CHAR OUTPUT STATE VECTOR TABLE
DW @@COS0-1
DW @@COS1-1
DW @@COS2-1
DW @@COS3-1
DW @@COS4-1
DW @@COS5-1
DW @@COS6-1
; COMMAND EXECUTION TABLE
CMDETB
DW @@EINIT-1
DW @@ELOAD-1
DW @@ESAVE-1
DW @@ERUN-1
DW @@ECHAIN-1
DW @@EDEL-1
DW @@ELOCK-1
DW @@EUNLK-1
DW @@ECLOSE-1
DW @@EREAD-1
DW @@EEXEC-1
DW @@EWRITE-1
DW @@EPOS-1
DW @@EOPEN-1
DW @@EAPND-1
DW @@EREN-1
DW @@ECAT-1
DW @@EMON-1
DW @@ENOMON-1
DW @@EPR-1
DW @@EIN-1
DW @@EMAXF-1
DW @@EAS-1
DW @@EINT-1
DW @@EBSV-1
DW @@EBLD-1
DW @@EBRUN-1
DW @@EVAR-1
EAT1
PAGE
;
; NON-RELOCATING ADRS
;
IBASVT
CHAIN DW @@IBCHN
RUN DW @@IBRUN
BREAK DW @@IBBRK
GO DW @@IBGO
CONT DW @@IBCONT ;BASIC CONT ENTRY POINT
IBVT DW @@IBCHN,@@IBRUN,@@IBBRK
DW @@IBGO,@@IBCONT
IBVTL EQU *-IBVT
;
AS1VT DW @@ASRUN1,@@ASRUN1,@@ASBRK1
DW @@IBGO,@@0
AS1VTL EQU *-AS1VT
;
AS2VT DW @@ASRUN2,@@ASRUN2,@@ASBRK2
DW @@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 IN 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 $E3E3 ; 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
ZPGFCB 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 IIB1
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
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 INIT/RESET
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 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 CHIN0
JMP INITC
CHIN0
LDA SVA
STA ($28),Y
JMP INCFD ;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
STX SVX
STY SVY
TSX
INX
INX
STX SVSTK
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 ; IF CR THEN CMD CHECK
LDA ESTATE ;ELSE: IF NOT EXECUTE
BEQ PRRTN ; THEN PRINT CHAR
BNE DRTNI ; ELSE: PRINT IF MON INPUT
COS3A
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
ORTN
JSR MVCSW
LDX SVSTK
TXS
LDREGS
LDA SVA ;ACU
LDY SVY ;Y
LDX SVX ;X
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 CMDRTN ;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 JSR GNXTC ;GO GET NEXT CHAR
BEQ SN6 ;BR IF COMMA OR CHAR
SN4 STA FNAME1,Y ;PUT INTO FILENAME
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
STA TEMP1A
LDA LBUFD ;SET PASS 1
;
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 ;OR 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
GNXTCR 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 ;CCB LENGTH
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
HN0
JSR GNBC ;GO GET CHAR
BEQ GN2A ;BR IF CR OR COMMA
;
SEC
SBC #$B0 ;CHAR – ASCII0
BMI GN4 ;BR IF LT0
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 #CRQDEL ;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 #CRQLCK ;SET LOCK
BNE ELGO
;
; EUNLK – UNLOCK A FILE
;
EUNLK
LDA #CRQUNL ;SET UNLOCK
ELGO
JSR OPEN ;OPEN FILE & UNLOCK
JMP ECLOSE ; CLOSE IT
;
; EVAR – VERIFY A FILE
;
EVAR
JMP DP1 ;*** PATCH ***
BRK
PAGE
;
; EREN – RENAME A FILE
;
EREN
LDA FN2ADR ;MOVE FILE NAME2
STA CCBFN2
LDA FN2ADR+1
STA CCBFN2+1
LDA #CRQRNM
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 #CRQOPN
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
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
JSR MVFN1 ;GO MOVE FILE NAME
JSR MVBUFP ;GO MOVE BUF PTRS
JSR OPNSUP ;GO SET UP OPEN
LDA TEMP1A ;SET OPEN REG
STA CCBREQ
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 #CRQCLS ;SET CLOSE
STA CCBREQ
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 ;GO 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 A+L
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
LDA #CREFNF
CMP CCBSTA
BNE EBLD2
JMP KLUTZ
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
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 LRNGTH
;
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 BLOCK
;
SV1
SV1A
STA CCBFUC ; SET 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 #CRQWR ; INDICATE WRITE
STA CCBREQ
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/O
STA CCBRQM
JSR DOSGO ; GO DO IT
JMP ECLOSE ; CLOSE FILE
PAGE
NBPER JMP ERNUl
;
; 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
;
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 - BLOK 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 #CRQRD ; READ
STA CCBREQ
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 ; GET BLOCK
JMP ECLOSE ; GO CLOSE FILE
;
MFULL
JSR ECLOSE ; GO CLOSE FILE
JMP MFERR ; AND GIVE ERR MSG
LD1
CMP CCBFUC ; TEST TYP
BEQ LD1C ; BR IF MATCH
LDX CMDNO
STX SVCMD
LSRA
BEQ LD1A ; BR IF PGM IS AS
JMP EINT ; GO FOR INTG 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 REQD
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 #CRQPOS ;INDICATE POSITION REQUIRED
STA CCBREQ
JSR DOSGO
RWPR RTS ;DONE
PAGE
;
;
; EINIT – EXECUTE INIT COMMAND
;
EINIT
LDA #V ; MUST HAVE
AND INOPTS ; VOL OPTION
BEQ INER
LDA CV ; AND VOL MUST
BEQ INER ; BR GT 0
LDA ASTART+1
STA CCBBSA
LDA #CRQFMT
JSR OPEN
JMP ESAVE
;
INER JMP CNF
;
; ECAT – PRINT CATALOG
;
ECAT
LDA #CRQDIR
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
;
LDY #30
JSR CLRFNA
LDX #FASBL
EAS1 LDA FASB-1,X ; MOVE SYSTEM FILE NAME
STA FNAME1-1,X
DEX
BNE EAS1
;
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 ; RETURN
;
PAGE
;
; EEXEC – EXEC CMD
;
EEXEC
JSR EOPEN ; OPEN FILE
LDA CFTABA
STA EFTABA ; MOVE TABLE POINTERS
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
JMP EXP2
EXP1 JSR MVBUFP
EXP2
LDA INOPTS ; GET OPTIONS
AND #R ; TEST R
BEQ EX2 ; BR IF NOT R
;
EX0 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 RECORD
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
LDA SVA ;CHAR IN SAVED ACU
STA CCBDAT ;PUT IN CCDBDATA 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
;
INCFD
JSR TSTRUN ;GO TEST RUN
LDA #6 ;SET OUT STE = 6
ICFD3
STA OSTATE ;TO CATCH ECHO
JSR RBYTE
BNE ICFD1 ;BR IF NOT ZERO CHAR
;
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
JMP ASRWPAT ;AS READ/WRITE > LINE # 255 PATCH
TR1
LDA $D9 ;GET INT RUN FLAG
BMI MVEFRT ; BR IF RUN
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
MVEFRT RTS
PAGE
;
; DOSGO – GOTO DOS
;
DOSGO
JSR DOSENT ;GO TO DOS
BCS DG1 ;BR IF ERROR
RTS ;DONE
;
DG1
LDA CCBSTA ;GET STATUS OF I/O
CMP #CREEOF ;EOF ?
BNE DG2 ;BR IF NOT
LDX #0 ;SET OTHER EIF
STX CCBDAT ; DONE
RTS
DG2
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
ERNUl 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/O 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
JSR ORTN1 ;OUTPUT CHAR
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
;
; 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 TXC1 ; 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 ERNUl
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 BFT1B
;
PLA ; SET APPLESOFT
STA ASHM1+1 ; UPPER MEM LIMITS
STA ASHM2+1
PLA
STA ASHM1
STA ASHM2
RTS
;
BFT1B
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 IN SWITCH
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
DW @@0,254 ;VOL RANGE
DW @@1,@@2 ;DRIVE RANGE
DW @@1,@@7 ;SLOT RANGE
DW @@1,32767 ;LENGTH RANGE
DW @@0,32767 ;REC NO RANGE
DW @@0,32767 ;REC BYTE NO RANGE
DW @@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,EML
PAGE
;
; MISC BUT REQD CELLS
;
CFTABA DW @@$182D ;CURRENT FILE TABLE POINTER
ISTATE DB $00 ;INPUT STATE
OSTATE DB $03 ;OUTPUT STATE
SVOUTS DW @@$FDF0 ;SAVED OUT SWITCH
SVINS DW @@$FD1B ;SAVED IN SWITCH
CNFTBS DB $03 ;CURRENT NO FILE TABLES
DFNFTB DB $03 ;DEFAULT NO FILE TABLES
SVSTK DB $F7 ;SAVED STACK PTR
SVX DB $00 ;DSAVED X REG
SVY DB $01 ;SAVED Y REG
SVA DB $A0 ;SAVED ACU
LBUFD DB $0E ;LINE BUFF DSPL
MONMOD DB $70 ;MONITOR MODE BITS
MC EQU $40 ;MONITOR CMDS
MI EQU $20 ;MONITOR INPUT
MO EQU $10 ;MONITOR OUTPUT
CMDNO DB $20 ;COMMAND NO
SVBL DB 0,0
SVCMD DB 0
TEMP1A DB $06
TEMP2A DB 1
INOPTS DB $30 ;INPUT OPTIONS
CUROPT ;CURRENT OPTIONS
CV DW @@$10 ;VOLUME
CD DW @@1 ;DRIVE
CS DW @@7 ;SLOT
CL DW @@1 ;RECORD LENGTH
CR DW @@0 ;RECORD NUMBER
CB DW @@0 ;RECORD BYTE
CA DW @@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 DW @@IOB ;5-ADR IOB
AVTOC DW @@VTOC ;6-ADR VTOC
AVOLDR DW @@VOLDIR ;7-ADR VOLDIR
AEND DW @@EDOS ;END OF DOS
;
CMDVT DW @@GOODIO-1 ;0-NULL
DW @@FOPEN-1 ;1-OPEN FILE
DW @@FCLOSE-1 ;2-CLOSE FILE
DW @@FREAD-1 ;3-READ FILE
DW @@FWRITE-1 ;4-WRITE DATA
DW @@FDEL-1 ;5-DELETE FILE
DW @@RDIR-1 ;6-READ DIRECTORY
DW @@FLOCK-1 ;7-LOCK A FILE
DW @@FUNLCK-1 ;8-UNLOCK A FILE
DW @@FRNME-1 ;9-RENAME
DW @@FPOSTN-1 ;10-POSITION A FILE
DW @@FFMT-1 ;FORMAT
DW @@FVAR-1 ; VARIFY
DW @@GOODIO-1 ;11-SPARE
;
RVT
DW @@GOODIO-1
DW @@RNXBYT-1 ;1-RD NEXT BYTE
DW @@RNXBLK-1 ;1-RD NEXT BLOCK
DW @@RSPBYT-1 ;2-RD SPECIFIC BYTE
DW @@RSPBLK-1 ;3-RD SPECIFIC BLOCK
DW @@GOODIO-1 ;4-SPARE
;
WVT
DW @@GOODIO-1
DW @@WNXBYT-1 ;1-WR NEXT BYTE
DW @@WNXBLK-1 ;WR NEXT BLOCK
DW @@WSPBYT-1 ;2-WR SPECIFIC BYTE
DW @@WSPBLK-1 ;3-WR SPECIFIC BLOCK
DW @@GOODIO-1 ;4- SPARE
EAT2
PAGE
;
; DOSENT – DOS EXTERNAL ENTRY POINT
; EXIT PARM
; CARRY CLEAR = OPERATION OK
; CARRY SET = ERROR
;
SC2
DOSENT
TSX
STX ENTSTK
JSR CLCFCB ;GO CALCULATE FCB
LDA CCBREQ ;GET REQUEST
CMP #CRQMAX ;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
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 FO2
CPX #0
BNE FO2
INX ;SET RL=256
FO2 STA DCBRCL
STX DCBRCL+1
;
JSR FNDFIL ;GO FIND FILE
BCC FO3 ;BR IF FOUND
; ;CREATE FILE
LDA #0
STA VDFILE+34,X
LDA #1
STA VDFILE+33,X
STX TEMP1 ;SAVE VDIR INDEX
STX DCBVDI
JSR GETSEC ;GO ALLOCATE SECTOR
LDX TEMP1
STA VDFILE+1,X ;PUT SECTOR INTO VDIR
STA DCBFDS ;PUT SECTOR AS FIRST 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 WRFDGO ;GO WRITE FILE DIRECTORY DONE CREATION
; DONE CREATION
LDX TEMP1 ;RE-GET INDEX
LDA #CREFNF
STA CCBSTA
;
FO3
LDA VDFILE,X ;MOVE FILE DIR TRACK
STA DCBFDT
LDA VDFILE+1,X ;MOVE FILE DIR SECTOR
STA DCBFDS
LDA VDFILE+2,X ;MOVE FILE USE CODE
STA CCBFUC
STA DCBFUC
LDA VDFILE+33,X
STA DCBNSA
LDA VDFILE+34,X
STA DCBNSA+1
;
LDA #255 ;INDICATE NO SECTOR
STA DCBCMS ;IN MEMORY
STA DCBCMS+1
LDA VTDMS ;MOVE MAX FD SECS
STA DCBDMS ;TO DCB
CLC
JMP RDFDIR ; READ 1ST DIRECTORY RECORD
;
;
;
;
DCBSUP
LDA #0
TAX
FO1 STA FCBDCB,X ;CLEAR DCB
INX
CPX #DCBLEN
BNE FO1
;
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
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 A 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
;
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
;
FLOCK 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
;
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
RD0 LDA VOLMES,X ; GET MSG CHAR
JSR PRINT ; PRINT IT
DEX ; DECREMENT COUNT
BPL RD0 ; 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
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 FCBB,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 FCBB,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
;
CLRSEC
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 CCBREQ ;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
;
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
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
;
; RDVDIR – READ VOLUME DIRECTOR
;
RDVDIR
PHP ;SAVES STATUS
JSR MVVDBA
;
PLP ;GET STATUS
BCS RVDA ;BR IF R0 NEXT
;
LDY VDIRSC ;GET LINK SECTOR
LDX VDIRTK ;GET FIRST TRK
BNE RDVGO ;GO READ
;
RVDA
LDX VDLTRK ;GET SECTOR
BNE RDVC ;BR IF A LINK
SEC ; SET END OF DIR
RTS
;
RDVC LDY VDLSEC ;GET SECTOR
RDVGO
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 – DECREMENT 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 LDY TEMP2 ;LOOKING FOR EMPTY
BNE FF5 ;BR IF NOT
;
MVFN
LDY #0 ;HAVE NEW ENTTRY
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
;
GS0
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
JSR 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 DCBRCL+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 ;ADD 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
ERRR10 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 $11 ;CUR VOL DIR TRK
CVDSEC DB $0B ;CUR VOL DIR SECTOR
CURCCB DB 0,0 ;CURRENT CCB ADR
ENTSTK DB $F5 ;ENTRY STACK POINTER
TEMP1 DB 0 ;TEMP BYTE 1
TEMP2 DB $0C ;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
VOLMES DB11 " EMULOV KSID"
VML EQU *-VOLMES-1
PAGE
;
; VTOC RECORD AREA
;
VTOC
VDOST DB 1 ; DOS TYPE
VDIRTK DB 17 ;COLUME DIRECTORY SECTOR
VDIRSC DB 12 ;VOLUME DIRECTORY SECTOR
VDOSRN DB 1 ; DOS RELEASE NUMBER
DB 1 ; SPARE
DB 1 ; SPARE
VVOLNO DB 16 ;VOLUME NUMBER
RMB 32 ; SPARE
VTDMS DB 122 ;MAX SECTORS IN A FILE DIR
VSPARE RMB 8 ;SPARES
;
VALCA1 DB 30 ;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 DW 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 0 ; 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
;
FCBB
;
; 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 *-FCBB ;FCB LENGTH
PAGE
;
; DOS PATCH AREA 1
SDP1
EDP1 EQU ORG2-2
DB 0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
DR2PAT ;*** PATCH *** (DOSREL - FIND END OF DOS)
LDA ZPGWRK+1 ;GET TOP OF RAM PAGE FOUND
AND #$DF ;SAVE 8K LESS THAN TOP OF RAM IF 16K, 32K, OR 48K SYS
STA ZPGFCB+1 ;LEAVE AS IS IF 20K, 24K, OR 36K SYSTEM
STX ZPGFCB ;ZERO LO
LDA (ZPGFCB,X) ;GET BYTE FROM (POSSIBLY NEW) TOP OF RAM
PHA ;SAVE IT TO STACK
STA LOC1 ;TEST FOR RAM AGAIN
DR2P1
TYA ;FIRST PASS=0
EOR LOC1
STA LOC1
TYA
EOR (ZPGWRK,X)
STA (ZPGFCB,X)
CMP LOC1
BNE DR2P3 ;BR IF NOT RAM
INY ;NEXT VERIFY PASS
BNE DR2P1
LDY ZPGFCB+1 ;GET TOP OF RAM PAGE IF TOOK
PLA ;RESTORE LAST BYTE READ FROM RAM
RTS ;RTN WITH (POSSIBLY NEW) TOP OF RAM PAGE
;
DR2P3
PLA ;RESTORE LAST BYTE READ FROM RAM
STA (ZPGFCB,X) ;PUT IT BACK IN RAM
LDY ZPGWRK+1 ;GET ORIG TOP OF RAM PAGE
RTS ;AND RETURN
;
; DOSLDR – DOS LOADER AND WRITTER
;
ORG ORG2
DOSLDR
; GARBAGED BOOT REC 0 HERE
RMB 254
GRSPG DB $36
GRPGC DB $48
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 BIO1 ;BR IF NOT SECTOR ZERO
LDY #0 ;SET TO SECTOR ZERO
INC IBTRK
BIO1 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 * ;*** PATCH *** (EVAR)
LDA #CRQVAR ;VERIFY COMMAND
JSR OPEN ;TRY VERIFY
LDA #CREFNF ;FILE NOT FOUND ERROR CODE
CMP CCBSTA ;TEST FILE NOT FOUND
BNE DP11 ;BR IF FOUND
JMP KLUTZ ;ELSE GO FIX THINGS
DP11
JMP ECLOSE ; FILE FOUND, CLOSE AND RTN
;
BOUND 256
ORG *-$20
EC3
NDPGS DB 0
BRWCNT DB 0
BSDSEC DB 0
BGNDOS DB 0
BAIOB DW @@IOB
ADOSLD DW @@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 $60 ;CONTROLLER SLOT NO.
IBDRVN DB 1 ;DRIVE NUMBER
IBVOL DB $FF ;VOLUME NUMBER
IBTRK DB $11 ;TRACK NUMBER
IBSECT DB $0B ;SECTOR NUMBER
IBDCTP DW @@DCT
IBBUFP DW @@$33EF ;POINTER TO BUFFER
IBDLEN DW @@0 ;DATA LENGTH
IBCMD DB 1 ;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 $10 ;STATUS MODIFIER BYTE
IBPSLT DB $60 ;PREVIOUS SLOT
IBPDRV DB 1 ;PREVIOUS DRIVE
IBSPAR RMB 2 ;IOB SPARES
DCT DB 0,1,$EF,$D8
DB 0
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
;
ZPORG EQU 0
FILDIR EQU ZPORG
FDUCDE EQU ZPORG ;FILE USE CODE
FDLTRK EQU ZPORG+1 ;LINK TO NXT DIR TRACK
FDLSEC EQU ZPORG+2 ;LINK TO NEXT DIR SECTOR
FDNSA EQU ZPORG+3 ;NO SECTOR ALLOCATED
FDLSDL EQU ZPORG+4 ;LAST SECTOR DATA LENGTH
FDFRS EQU ZPORG+5 ;1ST RELATIVE SECTOR IN THIS DIR
FDSPAR EQU ZPORG+7 ;SPARES
;
FDENT EQU ZPORG+12 ;START OF FILE ENTRIES (122)
FDTRK EQU 0 ;TRACK
FDSEC EQU 1 ;SECTOR
;
FDLAST EQU FILDIR+256
PAGE
;
***************************
* DISC-II *
* 13-SECTOR FORMAT *
* READ AND WRITE *
* SUBROUTINES *
* *
***************************
* *
* *
* COPYRIGHT 1978 *
* APPLE COMPUTER INC. *
* *
* ALL RIGHTS RESERVED *
* *
***************************
* *
* MAY 25, 1978 *
* WOZ *
* R. WIGGINTON *
* *
***************************
EJECT
***************************
* *
* CRITICAL TIMING *
* REQUIRES PAGE BOUND *
* CONSIDERATIONS FOR *
* CODE AND DATA *
* *
* -----CODE----- *
* *
* VIRTUALLY THE ENTIRE *
* 'WRITE' ROUTINE *
* MUST NOT CROSS *
* PAGE BOUNDARIES. *
* *
* CRITICAL BRANCHES IN *
* THE 'WRITE', 'READ', *
* AND 'READ ADR' SUBRS *
* WHICH MUST NOT CROSS *
* PAGE BOUNDARIES ARE *
* NOTED IN COMMENTS. *
* *
* -----DATA----- *
* *
* NBUF1, NBUF2, NBUF3, *
* NBUF4, AND NBUF5 ARE *
* 51-BYTE RAM BUFFERS *
* WHICH SHOULD ALL BE *
* LOCATED ON A SINGLE *
* PAGE BEGINNING WITH *
* NBUF1. (NBUF5 IS 52). *
* *
* NBUF6, NBUF7, AND *
* NBUF8 MUST NOT CROSS *
* PAGE BOUNDARIES AND *
* SHOULD BE LOCATED *
* ON A PAGE BEGINNING *
* WITH NBUF6. NBUF6 *
* AND NBUF7 ARE 51 BYTES *
* WHILE NBUF8 IS 52. *
* *
* NIBLIZING TABLE 'NIBL' *
* (32 BYTES) MUST NOT *
* CROSS PAGE BOUNDARY. *
* CONVERTS 5-BIT NIBLS *
* TO 7-BIT NIBLS. *
* *
* DENIBLIZING TABLE *
* 'DNIBL' MUST BE ON A *
* PAGE BOUNDARY, BUT *
* ONLY DNIBL,$AB TO *
* DNIBL,$FF NEED BE *
* USED. CONVERTS 7-BIT *
* NIBLS TO 5-BIT NIBLS. *
* *
***************************
EJECT
***************************
* *
* EQUATES *
* *
***************************
* *
* -----PRENIBL---- *
* AND POSTNIBL *
* *
***************************
BUF EQU $3E ;TWO BYTE POINTER.
*
* POINTS TO 256-BYTE
* USER BUFFER ANYWHERE
* IN MEMORY. PRENIBL
* CONVERTS USER DATA
* (IN BUF) INTO 5-BIT
* NIBLS 000ABCDE IN
* NBUF1 THROUGH NBUF8
* PRIOR TO 'WRITE'.
* POSTNIBL CONVERTS
* 5-BIT NIBLS ABCDE000
* BACK TO USER DATA
* (IN BUF) AFTER 'READ'.
*
NBUF1 EQU $3B00
NBUF2 EQU $3B33 ;OBSERVE THESE
NBUF3 EQU $3B66 ;PLACEMENTS
NBUF4 EQU $3B99 ;RELATIVE TO
NBUF5 EQU $3BCC ;PAGE STARTS!
NBUF6 EQU $3C00
NBUF7 EQU $3C33
NBUF8 EQU $3C66 ;(TO $BC99)
*
T0 EQU $26 ;TEMPS USED BY PRENIBL
T1 EQU $27 ; AND POSTNIBL.
T2 EQU $2A ;TEMP USED BY PRENIBL.
*
************************
* *
* ----READADR---- *
* *
************************
COUNT EQU $26 ;'MUST FIND' COUNT.
LAST EQU $26 ;'ODD BIT' NIBLS.
CSUM EQU $27 ;CHECKSUM BYTE.
CSSTV EQU $2C ;FOUR BYTES,
* CHECKSUM, SECTOR, TRACK, AND VOLUME.
*
************************
* *
* ----WRITE---- *
* *
* USES ALL NBUFS *
* AND 32-BYTE *
* DATA TABLE 'NIBL' *
* *
************************
WTEMP EQU $26 ;TEMP FOR DATA AT NBUF6,0.
SLOTZ EQU $27 ;SLOTNUM IN Z-PAG LOC.
SLOTABS EQU $678 ;SLOTNUM IN NON-ZPAG LOC.
*
************************
* *
* -----READ---- *
* *
* USES ALL NBUFS *
* USES LAST 54 BYTES *
* OF A CODE PAGE FOR *
* USED BYTES OF DNIBL *
* TABLE. *
* *
************************
IDX EQU $26 ;INDEX INTO (BUF).
DNIBL EQU $3A00 ;7-BIT TO 5-BIT NIBLS.
*
************************
* *
* ---- SEEK ---- *
* *
************************
TRKCNT EQU $26 ;HALFTRKS MOVED COUNT.
PRIOR EQU $27 ;PRIOR HALFTRACK.
TRKN EQU $2A ;DESIRED TRACK.
SLOTTEMP EQU $2B ;SLOT NUM TIMES $10.
CURTRK EQU $478 ;CURRENT TRACK ON ENTYR.
*
************************
* *
* ---- MSWAIT ---- *
* *
************************
MONTIMEL EQU $46
MONTIMEH EQU $47
*
************************
* *
* DEVICE ADDRESS *
* ASSIGNMENTS *
* *
************************
PHASEOFF EQU $C080 ;STEPPER PHASE OFF.
PHASEON EQU $C081 ;STEPPER PHASE ON.
Q6L EQU $C08C ;Q7L,Q6L=READ
Q6H EQU $C08D ;Q7L,Q6H=SENSE WPROT
Q7L EQU $C08E ;Q7H,Q6L=WRITE
Q7H EQU $C08F ;Q7H,Q6H=WRITE STORE
EJECT
****************************
* *
* PRENIBLIZE SUBR *
* *
****************************
* *
* CONVERTS 256 BYTES OF *
* USER DATA IN (BUF),0 *
* TO (BUF),255 INTO 410 *
* 5-BIT NIBLS (000ABCDE) *
* IN NBUF1 THROUGH NBUF8. *
* *
* ---- ON ENTRY ---- *
* *
* BUF IS 2-BYTE POINTER *
* TO 256 BYTES OF USER *
* DATA. *
* *
* ---- ON EXIT ----- *
* *
* A-REG: UNCERTAIN. *
* X-REG: UNCERTAIN. *
* Y-REG: HOLDS $FF. *
* CARRY: UNCERTAIN. *
* *
* NBUF1 THROUGH NBUF8 *
* CONTAIN 5-BIT NIBLS *
* OF FORM 000ABCDE. *
* *
* TEMPS T0, T1, T2 USED. *
* *
****************************
ORG $3800
* OBJ $B800
PRENIBL LDX #$32 ;INDEX FOR (51) 5-BYTE PASSES.
LDY #$0 ;USER BUF INDEX.
PNIB1 LDA (BUF),Y ;FIRST OF 5 USER BYTES.
STA T0 ;(ONLY 3 LSB'S USED)
LSRA
LSRA ;5 MSB'S TO LOW BITS.
LSRA
STA NBUF1,X ;FIRST OF 8 5-BIT NIBLS.
INY
LDA (BUF),Y ;SECOND OF 5 USER BYTES.
STA T1 ;ONLY 3 LSB'S USED)
LSRA
LSRA ;5 MSB'S TO LOW BITS.
LSRA
STA NBUF2,X ;SECOND OF 8 5-BIT NIBLS.
INY
LDA (BUF),Y ;THIRD OF 5 USER BYTES.
STA T2 ;(ONLY 3 LSB'S USED)
LSRA
LSRA ;5 MSB'S TO LOW BITS.
LSRA
STA NBUF3,X ;THIRD OF 8 5-BIT NIBLS.
INY
LDA (BUF),Y ;FOURTH OF 5 USER BYTES.
LSRA
ROL T2 ;LSB INTO T2.
LSRA
ROL T1 ;NEXT LSB INTO T1.
LSRA
ROL T0 ;NEXT LSB INTO T0.
STA NBUF4,X ;FOURTH OF 8 5-BIT NIBLS.
INY
LDA (BUF),Y ;FIFTH OF 5 USER BYTES.
LSRA
ROL T2 ;LSB INTO T2.
LSRA
ROL T1 ;NEXT LSB INTO T1.
LSRA
STA NBUF5,X ;FIFTH OF 8 5-BIT NIBLS.
LDA T0
ROLA ;NEXT LSB.
AND #$1F ;TRUNCATE TO 5 BITS.
STA NBUF6,X ;SIXTH OF 8 5-BIT NIBLS.
LDA T1
AND #$1F ;TRUNCATE TO 5 BITS.
STA NBUF7,X ;SEVENTH OF 8 5-BIT NIBLS.
LDA T2
AND #$1F ;TRUNCATE TO 5 BITS.
STA NBUF8,X ;EIGHTH OF 8 5-BIT NIBLS.
INY
DEX ;NEXT OF (51) 5-BYTE PASSES.
BPL PNIB1
LDA (BUF),Y
TAX
AND #$7 ;3 LSB'S OF LAST
STA NBUF8+$33 ; USER BYTE.
TXA
LSRA
LSRA
LSRA ;5 MSB'S OF LAST
STA NBUF5+$33 ; USER BYTE.
RTS
EJECT
************************
* *
* WRITE SUBR *
* *
************************
* *
* WRITES DATA FROM *
* NBUF1 TO NBUF8 *
* CONVERTING 5-BIT *
* TO 7-BIT NIBLS *
* VIA 'NIBL' TABLE. :
* *
* FIRST, NBUF6 TO *
* NBUF8, HIGH TO LOW *
* THEN, NBUF1 TO *
* NBUF5, LOW TO HIGH *
* *
* ---- ON ENTRY ---- *
* *
* X-REG: SLOTNUM *
* TIMES $10. *
* *
* NBUF1 TO NBUF8 *
* HOLD NIBLS FROM *
* PRENIBL SUBR. *
* (000ABCDE) *
* *
* ---- ON EXIT ----- *
* *
* CARRY SET IF ERROR. *
* (W PROT VIOLATION) *
* *
* IF NO ERROR: *
* *
* A-REG: UNCERTAIN. *
* X-REG: UNCHANGED. *
* Y-REG: HOLDS $00. *
* CARRY CLEAR. *
* *
* SLOTABS, SLOTZ, *
* AND WTEMP USED. *
* *
* ---- ASSUMES ---- *
* *
* 1 USEC CYCLE TIME *
* *
************************
WRITE SEC ;ANTICIPATE WPROT ERR.
LDA Q6H,X
LDA Q7L,X ;SENSE WPROT FLAG.
BMI WEXIT ; IF HIGH, THEN ERR.
STX SLOTZ ;FOR ZERO PAGE ACCESS.
STX SLOTABS ;FOR NON-ZERO PAGE.
LDA NBUF6
STA WTEMP ;FOR ZERO-PAGE ACCESS.
LDA #$FF ;SYNC DATA.
STA Q7H,X ;(5) WRITE 1ST NIBL.
ORA Q6L,X ;(4)
PHA ;(3)
PLA ;(4) CRITICAL TIMING!
NOP ;(2)
LDY #$A ;(2) FOR 11 NIBLS.
WSYNC ORA WTEMP ;(3) FOR TIMING.
JSR WNIBL7 ;(13,9,6) WRITE SYNC.
DEY ;(2)
BNE WSYNC ;(2*) MUST NOT CROSS PAGE!
LDA #$D5 ;(2) 1ST DATA MARK.
JSR WNIBL9 ;(15,9,6)
LDA #$AA ;(2) 2ND DATA MARK.
JSR WNIBL9 ;(15,9,6)
LDA #$AD ;(2) 3RD DATA MARK.
JSR WNIBL9 ;(15,9,6)
TYA ;(2) CLEAR CHKSUM.
LDY #$9A ;(2) NBUF6-8 INDEX.
BNE WDATA1 ;(3) ALWAYS. NO PAGE CROSS!!
WDATA0 LDA NBUF6,Y ;(4) PRIOR 5-BIT NIBL.
WDATA1 EOR NBUF6-1,Y ;(5) XOR WITH CURRENT.
* (NBUF6 MUST BE ON PAGE BOUNDARY FOR TIMING!!)
TAX ;(2) INDEX TO 7-BIT NIBL.
LDA NIBL,X ;(4) MUST NOT CROSS PAGE!
LDX SLOTZ ;(3) CRITICAL TIMING!
STA Q6H,X ;(5) WRITE NIBL.
LDA Q6L,X ;(4)
DEY ;(2) NEXT NIBL.
BNE WDATA0 ;(2*) MUST NOT CROSS PAGE!
LDA WTEMP ;(3) PRIOR NIBL FROM BUF6.
NOP ;(2) CRITICAL TIMING.
WDATA2 EOR NBUF1,Y ;(4) XOR NBUF1 NIBL.
TAX ;(2) INDEX TO 7-BIT NIBL.
LDA NIBL,X ;(4)
LDX SLOTABS ;(4) TIMING CRITICAL.
STA Q6H,X ;(5) WRITE NIBL.
LDA Q6L,X ;(4)
LDA NBUF1,Y ;(4) PRIOR 5-BIT NIBL.
INY ;(2) NEXT NBUF1 NIBL.
BNE WDATA2 ;(2*) MUST NOT CROSS PAGE!
TAX ;(2) LAST NIBL AS CHKSUM.
LDA NIBL,X ;(4) INDEX TO 7-BIT NIBL.
LDX SLOTZ ;(3)
JSR WNIBL ;(6,9,6) WRITE CHKSUM.
LDA #$DE ;(2) DM4, BIT SLIP MARK.
JSR WNIBL9 ;(15,9,6) WRITE IT.
LDA #$AA ;(2) DM5, BIT SLIP MARK.
JSR WNIBL9 ;(15,9,6) WRITE IT.
LDA #$EB ;(2) DM6, BIT SLIP MARK.
JSR WNIBL9 ;(15,9,6) WRITE IT.
LDA Q7L,X ; OUT OF WRITE MODE.
WEXIT LDA Q6L,X ; TO READ MODE.
RTS ; RETURN FROM WRITE.
*****************************
* *
* 7-BIT NIBL WRITE SUBRS *
* *
* A-REG OR'D PRIOR EXIT *
* CARRY CLEARED *
* *
*****************************
WNIBL9 CLC ;(2) 9 CYCLES, THEN WRITE.
WNIBL7 PHA ;(3) 7 CYCLES, THEN WRITE.
PLA ;(4)
WNIBL STA Q6H,X ;(5) NIBL WRITE SUB.
ORA Q6L,X ;(4) CLOBBERS ACC, NOT CARRY.
RTS
EJECT
**************************
* *
* READ SUBROUTINE *
* *
**************************
* *
* READS 5-BIT NIBLS *
* (ABCDE000) INTO *
* NBUF1 THROUGH NBUF8 *
* CONVERTING 7-BIT *
* NIBLS TO 5-BIT *
* VIA 'DNIBL' TABLE *
* *
* FIRST READS NBUF6 TO *
* NBUF8 HIGH TO LOW, *
* THEN READS NBUF1 TO *
* NBUF5 LOW TO HIGH *
* *
* ---- ON ENTRY ---- *
* *
* X-REG: SLOTNUM *
* TIMES $10. *
* *
* READ MODE (Q6L, Q7L) *
* *
* ---- ON EXIT ----- *
* *
* CARRY SET IF ERROR. *
* *
* IF NO ERROR: *
* A-REG: HOLDS $AA *
* X-REG: UNCHANGED. *
* Y-REG: HOLDS $00 *
* CARRY CLEAR. *
* *
* NBUF1 TO NBUF8 *
* HOLD 5-BIT *
* NIBLS ABCDE000. *
* *
* USES TEMP 'IDX'. *
* *
* ---- CAUTION ----- *
* *
* OBSERVE *
* 'NO PAGE CROSS' *
* WARNINGS ON *
* SOME BRANCHES!! *
* *
* ---- ASSUMES ---- *
* *
* 1 USEC CYCLE TIME *
* *
**************************
READ LDY #$20 ;'MUST FIND' COUNT.
RSYNC DEY ;IF CAN'T FIND MARKS
BEQ RDERR ;THEN EXIT WITH CARRY SET.
RDD1 LDA Q6L,X ;READ NIBL.
BPL RDD1 ;*** NO PAGE CROSS! ***
RSYNC1 EOR #$D5 ;DATA MARK 1?
BNE RSYNC ; LOOP IF NOT.
NOP ;DELAY BETWEEN NIBLS.
RDD2 LDA Q6L,X
BPL RDD2 ;*** NO PAGE CROSS! ***
CMP #$AA ;DATA MARK 2?
BNE RSYNC1 ; (IF NOT, IS IT DM1?)
LDY #$9A ;INIT NBUF6 INDEX.
* (ADDED NIBL DELAY)
RDD3 LDA Q6L,X
BPL RDD3 ;*** NO PAGE CROSS! ***
CMP #$AD ;DATA MARK 3?
BNE RSYNC1 ; (IF NOT, IS IT DM1?)
* (CARRY SET IF DM3!)
LDA #$00 ;INIT CHECKSUM.
RDATA1 DEY
STY IDX
RDD4 LDY Q6L,X
BPL RDD4 ;*** NO PAGE CROSS! ***
EOR DNIBL,Y ;XOR 5-BIT NIBL.
LDY IDX
STA NBUF6,Y ;STORE IN NBUF6 PAGE.
BNE RDATA1 ;TAKEN IF Y-REG NONZERO.
RDATA2 STY IDX
RDD5 LDY Q6L,X
BPL RDD5 ;*** NO PAGE CROSS! ***
EOR DNIBL,Y ;XOR 5-BIT NIBL.
LDY IDX
STA NBUF1,Y ;STORE IN NBUF1 PAGE.
INY
BNE RDATA2
RDD6 LDY Q6L,X ;READ 7-BIT CSUM NIBL.
BPL RDD6 ;*** NO PAGE CROSS! ***
CMP DNIBL,Y ;IF LAST NBUF1 NIBL NOT
BNE RDERR ;EQUAL CHKSUM NIBL THEN ERR.
RDD7 LDA Q6L,X
BPL RDD7 ;*** NO PAGE CROSS! ***
CMP #$DE ;FIRST BIT SLIP MARK?
BNE RDERR ; (ERR IF NOT)
NOP ;DELAY BETWEEN NIBLS.
RDD8 LDA Q6L,X
BPL RDD8 ;*** NO PAGE CROSS! ***
CMP #$AA ;SECOND BIT SLIP MARK?
BEQ RDEXIT ; (DONE IF IT IS)
RDERR SEC ;INDICATE 'ERROR EXIT'.
RTS ;RETURN FROM READ OR READADR.
EJECT
****************************
* *
* READ ADDRESS FIELD *
* *
* SUBROUTINE *
* *
****************************
* *
* READS VOLUME, TRACK *
* AND SECTOR *
* *
* ---- ON ENTRY ---- *
* *
* XREG: SLOTNUM TIMES $10 *
* *
* READ MODE (Q6L, Q7L) *
* *
* ---- ON EXIT ----- *
* *
* CARRY SET IF ERROR. *
* *
* IF NO ERROR: *
* A-REG: HOLDS $AA. *
* Y-REG: HOLDS $00. *
* X-REG: UNCHANGED. *
* CARRY CLEAR. *
* *
* CSSTV HOLDS CHKSUM, *
* SECTOR, TRACK, AND *
* VOLUME READ. *
* *
* USES TEMPS COUNT, *
* LAST, CSUM, AND *
* 4 BYTES AT CSSTV. *
* *
* ---- EXPECTS ---- *
* *
* NORMAL DENSITY NIBLS *
* (4-BIT), ODD BITS, *
* THEN EVEN. *
* *
* ---- CAUTION ---- *
* *
* OBSERVE *
* 'NO PAGE CROSS' *
* WARNINGS ON *
* SOME BRANCHES!! *
* *
* ---- ASSUMES ---- *
* *
* 1 USEC CYCLE TIME *
* *
****************************
RDADR LDY #$F8
STY COUNT ;'MUST FIND' COUNT.
RDASYN INY
BNE RDA1 ;LOW ORDER OF COUNT.
INC COUNT ;(2K NIBLS TO FIND
BEQ RDERR ; ADR MARK, ELSE ERR)
RDA1 LDA Q6L,X ;READ NIBL.
BPL RDA1 ;*** NO PAGE CROSS! ***
RDASN1 CMP #$D5 ;ADR MARK 1?
BNE RDASYN ; (LOOP IF NOT)
NOP ;ADDED NIBL DELAY.
RDA2 LDA Q6L,X
BPL RDA2 ;*** NO PAGE CROSS! ***
CMP #$AA ;ADR MARK 2?
BNE RDASN1 ; (IF NOT, IS IT AM1?)
LDY #$3 ;INDEX FOR 4-BYTE READ.
* (ADDED NIBL DELAY)
RDA3 LDA Q6L,X
BPL RDA3 ;*** NO PAGE CROSS! ***
CMP #$B5 ;ADR MARK 3?
BNE RDASN1 ; (IF NOT, IS IT AM1?)
* (LEAVES CARRY SET!)
LDA #$0 ;INIT CHECKSUM.
RDAFLD STA CSUM
RDA4 LDA Q6L,X ;READ 'ODD BIT' NIBL.
BPL RDA4 ;*** NO PAGE CROSS! ***
ROLA ;ALIGN ODD BITS, '1' INTO LSB.
STA LAST ; (SAVE THEM)
RDA5 LDA Q6L,X ;READ 'EVEN BIT' NIBL.
BPL RDA5 ;*** NO PAGE CROSS! ***
AND LAST ;MERGE ODD AND EVEN BITS.
STA CSSTV,Y ;STORE DATA BYTE.
EOR CSUM ;XOR CHECKSUM.
DEY
BPL RDAFLD ;LOOP ON 4 DATA BYTES.
TAY ;IF FINAL CHECKSUM
BNE RDERR ; NONZERO, THEN ERROR.
RDA6 LDA Q6L,X ;FIRST BIT-SLIP NIBL.
BPL RDA6 ;*** NO PAGE CROSS! ***
CMP #$DE
BNE RDERR ;ERROR IF NONMATCH.
NOP ;DELAY BETWEEN NIBLS.
RDA7 LDA Q6L,X ;SECOND BIT-SLIP NIBL.
BPL RDA7 ;*** NO PAGE CROSS! ***
CMP #$AA
BNE RDERR ;ERROR IF NONMATCH.
RDEXIT CLC ;CLEAR CARRY ON
RTS ;NORMAL READ EXITS.
EJECT
***************************
* *
* POSTNIBLIZE SUBR *
* *
***************************
* *
* CONVERTS 5-BIT NIBLS *
* OF FORM ABCDE000 IN *
* NBUF1 THROUGH NBUF8 *
* INTO 256 BYTES OF *
* USER DATA IN BUF. *
* *
* ---- ON ENTRY ---- *
* *
* X-REG: HOLDS SLOTNUM *
* TIMES $10. *
* *
* BUF IS 2-BYTE POINTER *
* TO 256 BYTES OF USER *
* DATA TO BE CONVERTED *
* TO 5-BIT NIBLS IN *
* NBUF1 THROUGH NBUF8 *
* PRIOR TO WRITE. *
* *
* ---- ON EXIT ----- *
* *
* A-REG: UNCERTAIN. *
* Y-REG: HOLDS $FF. *
* X-REG: HOLDS $FF. *
* CARRY: UNCERTAIN. *
* *
* 5-BIT NIBLS OF FORM *
* 000ABCDE IN 410 *
* BYTES FROM NBUF1 *
* TO NBUF8. *
* *
***************************
POSTNIB LDX #$32 ;INDEX FOR 51 PASSES.
LDY #$0 ;INDEX TO USER BUF.
POSTNB1 LDA NBUF6,X
LSRA
LSRA
LSRA
STA T1
LSRA
STA T0
LSRA
ORA NBUF1,X
STA (BUF),Y ;FIRST OF 5 USER BYTES.
INY
LDA NBUF7,X
LSRA
LSRA
LSRA
LSRA
ROL T1
LSRA
ROL T0
ORA NBUF2,X
STA (BUF),Y ;SECOND OF 5 USER BYTES.
INY
LDA NBUF8,X
LSRA
LSRA
LSRA
LSRA
ROL T1
LSRA
ROL T0
ORA NBUF3,X
STA (BUF),Y ;THIRD OF 5 USER BYTES.
INY
LDA T0
AND #$7
ORA NBUF4,X
STA (BUF),Y ;FOURTH OF 5 USER BYTES.
INY
LDA T1
AND #$7
ORA NBUF5,X
STA (BUF),Y ;FIFTH OF 5 USER BYTES.
INY
DEX ;NEXT OF 51 PASSES.
BPL POSTNB1 ;HANDLE LAST USER
LDA NBUF8+$33 ; BYTE DIFFERENTLY.
LSRA
LSRA
LSRA
ORA NBUF5+$33
STA (BUF),Y
RTS
EJECT
**************************
* *
* FAST SEEK SUBROUTINE *
* *
**************************
* *
* ---- ON ENTRY ---- *
* *
* X-REG HOLDS SLOTNUM *
* TIMES $10. *
* *
* A-REG HOLDS DESIRED *
* HALFTRACK. *
* (SINGLE PHASE) *
* *
* CURTRK HOLDS CURRENT *
* HALFTRACK. *
* *
* ---- ON EXIT ----- *
* *
* A-REG UNCERTAIN. *
* Y-REG UNCERTAIN. *
* X-REG UNDISTURBED. *
* *
* CURTRK AND TRKN HOLD *
* FINAL HALFTRACK. *
* *
* PRIOR HOLDS PRIOR *
* HALFTRACK IF SEEK *
* WAS REQUIRED. *
* *
* MONTIMEL AND MONTIMEH *
* ARE INCREMENTED BY *
* THE NUMBER OF *
* 100 USEC QUANTUMS *
* REQUIRED BY SEEK *
* FOR MOTOR ON TIME *
* OVERLAP. *
* *
* --- VARIABLES USED --- *
* *
* CURTRK, TRKN, COUNT, *
* PRIOR, SLOTTEMP *
* MONTIMEL, MONTIMEH *
* *
**************************
SEEK STA TRKN ;TARGET TRACK.
CMP CURTRK ;ON DESIRED TRACK?
BEQ SEEKXIT ; YES, HIT IT AND RETURN.
STX SLOTTEMP ;SAVE X-REG.
LDA #$0
STA TRKCNT ;HALFTRACK COUNT.
SEEK2 LDA CURTRK ;SAVE CURTRK FOR
STA PRIOR ; DELAYED TURNOFF.
SEC
SBC TRKN ;DELTA-TRACKS.
BEQ SEEKEND ;DONE, FINISH SEEK.
BCS OUT ;(MOVE OUT, NOT IN)
EOR #$FF ;CALC TRKS TO GO.
INC CURTRK ;INCR CURRENT TRACK (IN).
BCC MINTST ;(ALWAYS TAKEN)
OUT ADC #$FE ;CALC TRKS TO GO.
DEC CURTRK ;DECR CURRENT TRACK (OUT).
MINTST CMP TRKCNT
BCC MAXTST ; AND 'TRKS MOVED'.
LDA TRKCNT
MAXTST CMP #$C
BCC STEP ;IF > $B, USE $B.
LDA #$B
STEP TAY ;ACCELLERATION INDEX.
LDA CURTRK
AND #$3 ;INDEX TO 'CURRENT
ASLA ; PHASE' OF 4-PHASE
ORA SLOTTEMP ; STEPPER.
TAX
LDA PHASEON,X ;HIT NEXT PHASE
LDA ONTABLE,Y ; FOR 'ONTIME'.
JSR MSWAIT ;(100 USEC INTERVALS)
LDA PRIOR
AND #$3 ;INDEX TO 'PRIOR PHASE'
ASLA ; OF 4-PHASE STEPPER.
ORA SLOTTEMP
TAX
LDA PHASEOFF,X ;PRIOR PHASE OFF,
LDA OFFTABLE,Y ; THEN WAIT 'OFFTIME'.
JSR MSWAIT ;(100 USEC INTERVALS)
INC TRKCNT ;'TRACKS MOVED' COUNT.
BNE SEEK2 ;(ALWAYS TAKEN)
SEEKEND LDA #$FF ;DELAY 9.5 MSEC FOR
JSR MSWAIT ; SETTLING TIME.
LDX SLOTTEMP ;RESTORE X-REG.
SEEKXIT RTS ;RETURN.
EJECT
**************************
* *
* MSWAIT SUBROUTINE *
* *
**************************
* *
* DELAYS A SPECIFIED *
* NUMBER OF 100 USEC *
* INTERVALS FOR MOTOR *
* ON TIMING. *
* *
* ---- ON ENTRY ---- *
* *
* A-REG: HOLDS NUMBER *
* OF 100 USEC *
* INTERVALS TO *
* DELAY. *
* *
* ---- ON EXIT ----- *
* *
* A-REG: HOLDS $00. *
* X-REG: HOLDS $00. *
* Y-REG: UNCHANGED. *
* CARRY: SET. *
* *
* MONTIMEL, MONTIMEH *
* ARE INCREMENTED ONCE *
* PER 100 USEC INTERVAL*
* FOR MOTON ON TIMING. *
* *
* ---- ASSUMES ---- *
* *
* 1 USEC CYCLE TIME *
* *
**************************
MSWAIT LDX #$11
MSW1 DEX ;DELAY 86 USEC.
BNE MSW1
INC MONTIMEL
BNE MSW2 ;DOUBLE-BYTE
INC MONTIMEH ; INCREMENT.
MSW2 SEC
SBC #$1 ;DONE 'N' INTERVALS?
BNE MSWAIT ;(A-REG COUNTS)
RTS
EJECT
**************************
* *
* PHASE ON-, OFF-TIME *
* TABLES IN 100-USEC *
* INTERVALS. (SEEK) *
* *
**************************
ONTABLE DB $01,$30,$28
DB $24,$20,$1E
DB $1D,$1C,$1C
DB $1C,$1C,$1C
OFFTABLE DB $70,$2C,$26
DB $22,$1F,$1E
DB $1D,$1C,$1C
DB $1C,$1C,$1C
EJECT
**************************
* *
* 7-BIT TO 5-BIT *
* 'DENIBLIZE' TABL *
* *
* VALID CODES *
* $AB TO $FF ONLY. *
* ($DA NOT VALID) *
* *
* ---- CAUTION ---- *
* *
* INSURE THAT FOLLOWING *
* 'RE-ORG' IS OK. *
* *
**************************
ORG $3AAB
* OBJ $BAAB
DB $00,$01,$08
DB $10,$18,$02
DB $03,$04,$05
DB $06,$20,$28
DB $30,$07,$09
DB $38,$40,$0A
DB $48,$50,$58
DB $0B,$0C,$0D
DB $0E,$0F,$11
DB $12,$13,$14
DB $15,$16,$17
DB $19,$1A,$1B
DB $1C,$1D,$1E
DB $21,$22,$23
DB $24,$60,$68
DB $25,$26,$70
DB $78,$27,$80
DB $88,$90,$29
DB $2A,$2B,$2C
DB $2D,$2E,$2F
DB $31,$32,$33
DB $98,$A0,$34
DB $A8,$B0,$B8
DB $35,$36,$37
DB $39,$3A,$C0
DB $C8,$D0,$3B
DB $3C,$D8,$E0
DB $3E,$E8,$F0
DB $F8
EJECT
**************************
* *
* 5-BIT TO 7-BIT *
* NIBL CONVERSION *
* TABLE *
* *
**************************
* *
* CODES $AA, $D5 *
* NOT USED *
* *
**************************
ORG $3C9A
* OBJ $BC9A
NIBL DB $AB,$AD,$AE
DB $AF,$B5,$B6
DB $B7,$BA,$BB
DB $BD,$BE,$BF
DB $D6,$D7,$DA
DB $0DB,$DD,$DE
DB $DF,$EA,$EB
DB $ED,$EE,$EF
DB $F5,$F6,$F7
DB $FA,$FB,$FD
DB $FE,$FF
DB $1C,$1C,$1C
*
DB $00,$00,$00
DB $A4,$2D,$B9,$D0,$3C,$A0,$05,$4C
DB $0A,$3E,$00,$00,$00,$00,$00,$00
DB $00,$05,$0A,$02,$07,$0C,$04,$09
DB $01,$06,$0B,$03,$08,$00,$00,$00
DB $00,$00,$00,$00,$00,$00,$00,$00
DB $00,$00,$00,$00,$00,$00,$00,$00
DB $00,$00,$00,$00,$00,$00,$00,$00
DB $00,$00,$00,$00,$00,$00,$00,$00
**************************
* *
* RWTS ENTRY POINT *
* *
**************************
VOLFND EQU $2F
TRKFND EQU $2E
SECFND EQU $2D
DRIVNO EQU $35
DEVCTBL EQU $3C
FMTTRKC EQU $41
IOBPL EQU $48
FMTMASK EQU $4A
FMTSEC EQU $4B
RETRYCNT EQU $578
SLOT EQU $5F8
SETWRT EQU $C08F
SETRD EQU $C08E
WRTDAT EQU $C08D
RDDATA EQU $C08C
DRVSL2 EQU $C08B
DRVSL1 EQU $C08A
DRVON EQU $C089
DRVOFF EQU $C088
PHASE1OFF EQU $C082
PHASE2OFF EQU $C084
PHASE3OFF EQU $C086
ORG DISKIO
* OBJ $BD00
RWTS
STY IOBPL ;SAVE IOB ADDRESS
STA IOBPL+1
LDY #$1 ;GET NEW SLOT #
LDA (IOBPL),Y
TAX ;SAVE SLOT # TO X
STY $4F8 ;SET SEEK CNT=1
LDY #$F ;SEE IF SLOT HAS CHANGED
CMP (IOBPL),Y
BEQ L3D2D ;BR IF SAME SLOT
TXA ;SAVE NEW SLOT #
PHA
LDA (IOBPL),Y ;GET OLD SLOT #
TAX
PLA
PHA ;NEW SLOT # BACK TO STACK
STA (IOBPL),Y ;SET NEW SLOT NUMBER
LDA SETRD,X ;SET READ MODE
L3D1E
LDY #$8 ;DELAY UNTIL DATA IS STABLE
LDA RDDATA,X
L3D23
CMP RDDATA,X
BNE L3D1E ;BR IF DRIVE STILL SPINNING
DEY
BNE L3D23 ;LONG ENOUGH? BR UNTIL OLD DRIVE OFF
PLA ;GET NEW SLOT #
TAX
L3D2D
LDA SETRD,X ;INSURE IN READ MODE
LDA RDDATA,X ;GET THE DATA
LDA RDDATA,X
PHA ;DELAY FOR DISK DATA TO CHANGE
PLA
STX SLOT ;SET SLOT
CMP RDDATA,X ;CHECK RUNNING
PHP ;SAVE CHECK RESULTS TO STACK
LDA DRVON,X ;TURN DRIVE ON
LDY #$6 ;MOVE IBDCTP & IBBUFP PTRS TO PAGE 0
L3D44
LDA (IOBPL),Y
STA $0036,Y ;PTRS DESTINATION ON PG 0
INY
CPY #$A ;ALL PTRS MOVED?
BNE L3D44 ;MOVE MORE IF NOT
LDY #2 ;GET DRIVE #
LDA (IOBPL),Y
LDY #$10 ;SAME DRIVE USED BEFORE?
CMP (IOBPL),Y
BEQ L3D5E ;BR IS SO
STA (IOBPL),Y ;ELSE SET CURR DRV #
PLP ;RESTORE CHECK RUNNING STATUS
LDY #$0 ;SET Z FLAG
PHP
L3D5E
RORA ;BY GOING INTO CARRY
LDA DRVSL1,X ;SELECT DRIVE 1
BCS L3D67 ;CARRY STILL SET - DRIVE 1 IT IS
LDA DRVSL2,X ;ELSE SELECT DRIVE 2
L3D67
ROR DRIVNO ;SAVE SELECTED DRV TO PG 0
LDY #$2 ;GET MOT ON TIME LO FROM DEVCTBL
LDA (DEVCTBL),Y
STA MONTIMEL ;SAVE LO
INY
LDA (DEVCTBL),Y ;GET MOT ON TIME HI FROM DEVCTBL
STA MONTIMEH ;SAVE HI
INY ;Y=4, SET TO IOB TRK
LDA (IOBPL),Y ;GET DESIRED TRACK
JSR MYSEEK ;GO SEEK
PLP ;WAS MOTOR ON?
BNE L3D8A ;SKIP DELAY AND TRY TRACK IF SO
L3D7D
LDY #$12 ;DELAY 100 USEC PER COUNT
L3D7F
DEY
BNE L3D7F
INC MONTIMEL
BNE L3D7D
INC MONTIMEH
BNE L3D7D ;COUNT UP TO $0000
*
* DISK IS UP TO SPEED
* IF NOT FORMAT, LOCATE CORRECT SECTOR
*
L3D8A
LDY #$C
LDA (IOBPL),Y ;GET COMMAND CODE #
BEQ L3DE5 ;BR IF NULL COMMAND
CMP #$4 ;FORMAT?
BEQ L3DE7 ;BR IF SO
RORA ;SET CARRY=1 FOR READ, 0 FOR WRITE
PHP ;AND SAVE THAT
BCS L3D9B ;BR IF READ
JSR PRENIBL ;MUST PRENIBBLIZE FOR WRITE
L3D9B
LDY #$30 ;48 RETRIES
STY RETRYCNT ;SAVE RETRY COUNT
L3DA0
LDX SLOT ;GET SLOT # INTO X
JSR RDADR ;READ NEXT ADDRESS FIELD
BCC L3DC7 ;BR IF GOOD READ
L3DA8
DEC RETRYCNT ;DEC RETRY COUNT
BPL L3DA0 ;IF HAVEN'T TRIED ENOUGH, TRY AGAIN
LDA $478 ;GET TRACK WE WANT
PHA ;SAVE IT
LDA #$60 ;RECALIBRATE TO TRK 96
JSR L3E82
DEC $4F8 ;ONCE TOO MANY?
BNE L3DDE ;TRIED TO RECAL TOO MANY
LDA #$0 ;MOVE TO TRK 0
JSR MYSEEK
PLA
L3DC1
JSR MYSEEK ;GO TO CORRECT TRACK
JMP L3D9B ;LOOP BACK, TRY AGAIN ON THIS TRK
L3DC7
LDY TRKFND ;ON THE RIGHT TRACK?
CPY $478
BEQ L3DF0 ;BR IF SO
LDA $478 ;SAVE DESTINATION TRK
PHA
TYA
JSR L3E82
PLA
DEC RETRYCNT ;SHOULD WE RESEEK?
BPL L3DC1 ;YES - RESEEK
BMI L3DA8 ;NO - RECALIBRATE
L3DDE
PLA ;REMOVE CURTRK
LDA #$40 ;BAD DRIVE ERROR
L3DE1
PLP
JMP L3E29 ;GO HANDLE ERROR
L3DE5
BEQ L3E27 ;ALL DONE
L3DE7
LDY #$3 ;GET VOLUME #
LDA (IOBPL),Y
STA VOLFND ;SAVE TO PG 0
JMP DSKFORM ;GO FORMAT
L3DF0
LDY #$3 ;IS THE RIGHT DISK IN?
LDA (IOBPL),Y ;GET DESIRED VOLUME
PHA ;SAVE VOLUME #
LDA VOLFND ;GET ACTUAL VOLUME
LDY #$E ;INDICATE VOLUME FOUND
STA (IOBPL),Y
PLA ;GET DESIRED VOLUME BACK
BEQ L3E06 ;DESIRED VOLUME MATCHES ALL
CMP VOLFND
BEQ L3E06 ;YES...IT WAS CORRECT
LDA #$20 ;SOMEONE SWITCHED DISKS!
BNE L3DE1 ;ALWAYS
L3E06
LDY #$5 ;TO ALLOW FOR INTERLEAVE
LDA SECFND ;GET REQUESTED LOGICAL SECTOR
L3E0A
CMP (IOBPL),Y
BEQ L3E17 ;FOUND OUR DESIRED SECTOR
DEC RETRYCNT ;ADJUST RETRY COUNT
BPL L3DA0
LDA #$80
BNE L3DE1 ;NO, KEEP TRYING
*
* SECTOR FOUND
*
L3E17
PLP ;GOT OUR SECTOR
BCC L3E32 ;CARRY WAS SET FOR WRITE OPERATION
JSR READ ;GO READ
PHP ;SAVE STATUS OF READ OPERATION
BCS L3DA8 ;CARRY SET IF BAD READ
PLP ;ADJUST STACK
JSR POSTNIB ;DECODE INTO REAL DATA
LDX SLOT ;GET SLOT # INTO X
L3E27
CLC ;INDICATE NO ERROR
DB $24 ;SKIP NEXT SEC TO MAINTAIN NO ERROR
L3E29 ; DO USELESS BIT INSTR INSTEAD
SEC ;INDICATE AN ERROR
LDY #$D ;SET ERROR #
STA (IOBPL),Y
LDA DRVOFF,X ;TURN DRV MOTOR OFF
RTS
L3E32
JSR WRITE ;WRITE NIBBLES NOW
BCC L3E27 ;BR IF NO ERRORS
LDA #$10 ;DISK IS WRITE PROTECTED
BCS L3E29 ;ALWAYS!
**************************
* *
* SEEK ROUTINE *
* *
* SEEKS TRACK 'N' IN *
* SLOT #X/16 *
* IF DRIVNO IS NEGATIVE, *
* ON DRIVE 1 *
* IF DRIVNO IS POSITIVE, *
* ON DRIVE 2 *
* *
**************************
MYSEEK
PHA ;PRESERVE ACC
LDY #$1 ;TWO PHASE DISK?
LDA (DEVCTBL),Y
RORA ;GET # OF PHASES INTO CARRY
PLA
BCC L3E4C ;BR IF 1 PHASE PER TRK
ASLA
JSR L3E4C
LSR $478 ;DIVIDE BACK DOWN
RTS
*
L3E4C
STA TRKFND ;SAVE DEST TRACK (*2)
LDA PHASEOFF,X
LDA PHASE1OFF,X
LDA PHASE2OFF,X
LDA PHASE3OFF,X
JSR L3E7B
LDA $478,Y
BIT DRIVNO ;IF MINUS, ON DRV 0
BMI L3E67
LDA $4F8,Y ;ELSE GET DRV 1 TRACK
L3E67
STA $478 ;CURRENT TRACK
LDA TRKFND ;DESTINATION TRACK
BIT DRIVNO ;UPDATE SLOT DEPENDENT
BMI L3E75 ; LOCATIONS WITH TRACK
STA $4F8,Y ; INFORMATION
BPL L3E78 ;ALWAYS!
L3E75 STA $478,Y
L3E78 JMP SEEK ;GO SEEK
L3E7B
TXA ;SET Y=SLOT #
LSRA
LSRA
LSRA
LSRA
TAY
RTS
*
* SET SLOT DEPENDENT TRACK LOCATION
*
L3E82
PHA ;SAVE DEST TRACK
LDY #$2
LDA (IOBPL),Y
RORA ;GET DRIVE # INTO CARRY
ROR DRIVNO ;INTO (DRIVENO)
JSR L3E7B ;SETUP Y REG
PLA
ASLA ;ASSUME TRACK IS HELD *2
BIT DRIVNO
BMI L3E98 ;IF ON DRIVE 1(1), DRIVNO MINUS
STA $4F8,Y ;SAVE DRV 2 TRACK
BPL L3E9B ;ALWAYS
L3E98
STA $478,Y ;ELSE SAVE DRV 1 TRACK
L3E9B
RTS
**************************
* *
* FORMAT ROUTINE *
* *
**************************
DSKFORM
LDA #$80 ;FAKE DRV 0 TRACK
STA $478
LDA #$0 ;SET TRACK TO 0
STA FMTTRKC ;SAVE FORMAT TRACK COUNTER
JSR SEEK ;GO THERE
LDA #$AA ;MASK FOR ODD-EVEN ENCODING
STA FMTMASK ;SAVE TO PG 0
LDY #$50 ;ATTEMPTS COUNT
L3EAE
STY MONTIMEH ;SAVE # OF ATTEMPTS
LDA #$27 ;39 SELF-SYNC NIBBLES
STA FMTSEC ;SAVE COUNT
LDA WRTDAT,X ;TURN OFF WRITE
LDA SETRD,X
*
* WRITE GAP
*
LDA #$FF ;GET SYNC BYTE
STA SETWRT,X ;WRITE IT
CMP RDDATA,X ;READ IT BACK
BIT $0000
L3EC4
DEY ;ADJUST WRITE ATTEMPTS
BEQ L3ED6 ;BR IF GOOD WRITE
PHA ;ELSE DELAY
PLA
NOP
L3ECA
PHA ;DELAY SOME MORE
PLA
NOP
NOP
STA WRTDAT,X ;WRITE AGAIN
CMP RDDATA,X ;READ IT BACK
BCS L3EC4 ;BR IF STILL NOT GOOD
L3ED6
DEC FMTSEC ;GOOD WRITE, SO DEC SYNC COUNT
BNE L3ECA ;WRITE NEXT
LDY MONTIMEH
NOP
NOP
BNE L3EE6 ;BR IF MOTOR TIME GOOD
L3EE0
PHA ;DELAYS
PLA
PHA
PLA
CMP ($0000,X)
L3EE6
NOP ;DELAY
*
* WRITE SECTOR ROUTINE
*
L3EE7
STA WRTDAT,X
CMP RDDATA,X
DEY
BNE L3EE0
*
* WRITE ADDR FIELD PROLOGUE
*
LDA #$D5 ;ADDR MARK 1
JSR WBYTE1
LDA #$AA ;ADDR MARK 2
JSR WBYTE
LDA #$B5 ;ADDR MARK 3
JSR WBYTE
LDA VOLFND ;WRITE ODD-EVEN ENCODED VOLUME
JSR EOWBYTE
LDA FMTTRKC ;WRITE ODD-EVEN ENCODED TRACK
JSR EOWBYTE
LDA FMTSEC ;WRITE ODD-EVEN ENCODED SECTOR
JSR EOWBYTE
LDA VOLFND ;CALC CHECKSUM BY EOR'ING VOLUME,
EOR FMTTRKC ; TRACK, AND SECTOR
EOR FMTSEC
PHA
LSRA
ORA FMTMASK ;WITH $AA
STA WRTDAT,X ;WRITE CHECKSUM ODD BITS
CMP RDDATA,X
PLA
ORA #$AA
JSR WBYTE1 ;WRITE CHECKSUM EVEN BITS
*
* WRITE ADDR FIELD EPILOGUE
*
LDA #$DE ;BIT-SLIP 1
JSR WBYTE
LDA #$AA ;BIT-SLIP 2
JSR WBYTE
LDA #$EB ;BIT-SLIP 3
JSR WBYTE
LDA #$FF ;WRITE SYNC BYTE
JSR WBYTE
*
* WRITE DATA FIELD
*
LDY #$2 ;WRITE IN TWO PASSES....
STY MONTIMEL
LDY #$AD ;...OF 173 BYTES EACH PASS (346 BYTES)
BNE L3F46
L3F40
DEY ;ADJUST # BYTES WRITTEN
BEQ L3F50
PHA ;GET $FF DATA FIELD BYTE BACK
PLA ;RE-SAVE IT
NOP ;DELAY SOME
L3F46
PHA ;GET DATA BYE BACK
PLA ;RESAVE
STA WRTDAT,X ;WRITE IT
CMP RDDATA,X
BCS L3F40 ;WRITE SOME MORE
L3F50
DEC MONTIMEL ;TWO PASSES COMPLETE?
BNE L3F46 ;DO ANOTHER PASS IF NOT
LDY MONTIMEH
CLC ;FOR ADC WITHOUT CARRY
BIT $0000
STA WRTDAT,X
LDA RDDATA,X
LDA FMTSEC ;GET SECTOR
ADC #$A ;3 SECTOR INTERLEAVE
STA FMTSEC ;RESAVE SECTOR
SBC #$C ;13 SECTORS DONE?
BEQ L3F73 ;BR IF SO
BCS L3F6C ;MORE SECTORS TO WRITE
DB $2C ;SKIP NEXT STA OF SECTOR, DO USELESS BIT INSTEAD
L3F6C
STA FMTSEC
LDA #$FF ;SYNC BYTE
JMP L3EE7 ;GO WRITE ANOTHER SECTOR
L3F73
PHA ;GET DATA BYTE BACK
PLA ;AND RESAVE
LDY MONTIMEH
LDA WRTDAT,X
LDA SETRD,X ;TURN OFF WRITE MODE
BMI L3FB3
DEY
L3F80
PHA ;DELAYS
PLA
NOP
NOP
BIT $0000
PHA
PLA
DEY
BNE L3F80
JSR RDADR ;VERIFY SECTOR ADDRESS
BCS L3F94 ;BR IF READ ADDRESS ERROR
LDA SECFND
BEQ L3F9E
L3F94
LDY MONTIMEH ;GET TRACK FMT ATTEMPTS
DEY ;DEC ATTEMPTS MADE
CPY #$10 ;DID WE TRY ENOUGH?
BCC L3FB3 ;BR IF ERROR ... WE TRIED ENOUGH
JMP L3EAE ;ELSE TRY AGAIN
L3F9E
INC FMTTRKC ;INC TRACK PTR
LDA FMTTRKC ;GET NEXT TRACK
CMP #$23 ;DID WE DO ALL 35 TRACKS?
BCS L3FB8 ;BR IS SO
ASLA ;ELSE GO TO NEXT TRACK
JSR SEEK
LDY MONTIMEH ;ADJUST # OF ATTEMPTS
INY
INY
STY MONTIMEH
JMP L3EAE ;GO FORMAT NEXT TRACK
L3FB3
LDA #$40 ;ERROR
JMP L3E29
L3FB8
JMP L3E27 ;ALL WENT WELL
*
* WRITE ODD BITS, THEN EVEN BITS OF A BYTE
*
EOWBYTE
PHA ;SAVE IT
LSRA ;ODD BITS FIRST
ORA FMTMASK ;WITH $AA
STA WRTDAT,X ;WRITE IT
CMP RDDATA,X
PLA ;RESTORE BYTE
CMP ($0000,X)
ORA #$AA ;GET EVEN BITS
**************************
* *
* WRITE A BYTE TO DISK *
* *
**************************
WBYTE1
NOP
WBYTE
PHA ;SAVE BYTE TO STACK
PLA ;GET IT BACK
NOP ;DELAY
STA WRTDAT,X ;WRITE IT
CMP RDDATA,X
RTS
**************************
* *
* FIX FOR A BUG WITH *
* APPLESOFT II *
* READ/WRITE STATEMENTS *
* (LINES GT 255 ARE *
* IGNORED!) *
* *
**************************
ASRWPAT
INX ;BUMP HIGH BYTE OF LINE #
BEQ ASRWP1 ;BR IF HIGH AS WE CAN GO
RTS ;ELSE LINE # GT 255, SO RETURN
ASRWP1 JMP ICFDB ;NOT RUN MODE - CLOSE FILE
*
ORG AEC2
DB 0
END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment