ML  X c0C)HCCH Mhhݩh `eCDiCD`  RPH   * 1H0芢@) Y0.Ș`i#(PM\ \b Pgi 0 @ $ ࠮UY   0DDԝLyȀi N@ )?HI   Y0`HIJH)* J j *  hJJJ)HJ   h i    YS S0 i`  !"#$%&'()*+,-./0123456789:;<=>?@H J3xj2h)1 |9 ӭ45(420 * (0241өX.`  ? *^)Lkl  k*PE 5 LN(G 2 gh ` ghgL ( 2 L<(0d( L ^E0O +)$IC H @8 f e h q  |_ 8cd CDL> CFa M  L< ?^)La`2'")*F$F$F$F$F$ 5 )ШF/Șa]`efС,L>/A! A^)Za`@ ܬ/^)(")")`$F$F$F 5$/L /aF@__(LN`ae$$%8(`()` ? % 2L< ?^)^>_f i ;gCh) qkl5\   Zc[d 4akl L>@^LZ>_ 3L kJjjj^^ e fE]_agh`L>:$ȱ$@+[_#{ %  Խji! ai % 2 I   J C H h  ˰ %  ;  q LZ 2  ,  H `L> ,/ % k/ q Ơ? ѩ/ | H /L_0?MdLc 3_MfLe N`aL<L>cLdMaNL< ?"(+ըHH`Q R !   $ . FȑF! /GF \H"+0+* ! F s L>cm: J~cTF1F  *c+)5! c (, c)1JJJc(c*d I ,0  Xi N dF4 5 ,8,0 ʩ0H 2h     i D JD bbFL>vij`*&!ߍ*@h ] 0 ^0`ߍ c 0l$$%()()%*&J%H,@hH hH@,h $% 8i8$(%)0hhH ]h`() c 0H c 0 h`hhh&JJ ]( ll  L>0 q/qcdHH 99 H H  I9 9 NY 2H  >8 d c  qFcdL HII/ Ih8`h`Lcdc`cd`u F E KE]L</auF a0BF/aɜɛ׽]E ;  qW  KFL FREE SECTORS CH) *Fh ):FȽ F FCIH' 0 d  i:Fȩ/F.a`CD/08HDICIHȰ/F`ȱ$>.+.i ȱ$:刄H !A I Hȱ$*?ȝ 2. ? [_{ ,0-:) 0$:>WI  IТ,L>H  0hLY k i j`C ?(  0(C.` E *! .ii  c0N EE 1 EC)0')AY)ע ? 0E088FG \dc  (HhLcL3 ^J ^ Lrfe 0=ghecfdefa``_Z_0  _ 3LMHFhȑFȽaF^0 ] FFL3ekfl\cZd[L3 ef7 | 40^ 0 FJJ]1FfȱFeȱF``B!08`]EE 1 8. *D}iji( AʩLMW!)   XȌVȌY W`VVWH8 hYaHXY8 XH hHH \h hX` *Hh I8ih( a ( a(!`L\CJfCJfCJfCDfC` qV  HII  INYh `h`c)8jHciPdijIjFIjFIjh` qV I38 8H0 I  ' H L>8jY8j NYY &I &I &IHeH.eIif  `!.莼 2Jjj }.b Ȉ!b FG` ɩL> z  e H^04 \ Ȍ  8 i h !`I0 `C Y%.`DOS SYS I  ` kݩ.C/`WV.b۩bѤC9`CLJ G  ,F0(BԝDEI V0 : , BLVDE`D1:*AR08hhJ ȱHȱIȱBȱDȱEeeHHLV)  1*  ,,p-  0  &  '0   Lv)l, 0  &LD1:MEM.SAVE:D1:DUP.SYSFXMUFI)vCD1:DOS.SYS n  * \*`آ R'S )ɀ@  T))% CError loading MEM.SAV or memory!  0* a*b*c*d* R Hc*JSDc*J-=d* 0b*ʈд =}MyDOS 4.53/4- Copyright 1988,˛Disks 1H 8R D: = D1: = =1-8.Dir of D1:-D8: *. Dir of D:A. Disk Directory K. Save MemoryB. Run Cartridge L. Load MemoryC. Copy File(s) M. Run at AddressD. Delete File(s) N. Load MEM.SAVE. Rename File(s) O. Change Config.F. Lock File(s) P. Set DensityG. Unlock File(s) Q. Make DirectoryH. Write DOS Files R. Pick DirectoryI. Initialize Disk S. Set RAMdisk #J. Duplicate Disk V. Set Verify Flag  @莻( 0  =Select Item ( for menu):@  =ɛL)1L,*L,:W@ ,,L=No such item!L), -0{ ПFull directory name?Z"L.Directory to be used as 'D:'? @ A(5)L.(I: 輿ȱޝL), CInvalid directory!L@( (0Le-File source, destination? '( @C۩wڭ8wܭC B8'0 @(ߍeލd(DЍ( ? 8' B Bȱޙ':>Ȍ(C0J* .B 9'ȱ/.* #,ɛȝ9' ߰ B |?,(0L), 'ut(9'3?&' .'Ƚ9'?&'  .و'Q?''(#( = =-->' =Q =YR_o (J(  0?B݋''BJ)`''utz0( ?(L|0L),L@nDisk to FORMAT: A B(UTލ1 =(Press for Enhanced Dns)Type to Format Drive 8: =AIYZNj[R VL@L),D1:DUP.SYSDrive to write DOS files to? AH1:*J)2I) Z B hpI) ?<2UTC٩vة۩.کL;Source, Destination (Sectors)? A)((8'( A)((((( @(0% =Insert both disks, type = B ( A((/( DB(( CDrives not compatible!J(j(8'Hh''h(ɛy CInvalid options! N@-&& N@)׍&&(&&&۩ک&&&&8* 84&&&& 848*8(ܭ(ݥwC, !CNot enough memory! ک&&`(Mh  & >L@&i &&&&mm   >  &((&թԥԍ(Ս(((( ( ((Cw((ՠԍ((,(0"( (( >"m(m( & &("L),  ( BL4,(, =Insert DESTINATION disk, press =Nͻ I) b( 0J) @((ԭ(խ( ( (((L4Drive, new density: A8'ɛ CDrive unchanged.(ު#90٨Ȍ(SD  qBL)xԌҭHӭ@@ ʎӆ@ӭ@@ :  $ӹ@hөԥX` Aˠ =RAM disk present? =NL08 =xlon or E type RAMdisk? =Aό $ L   M   A1| =6: ' =No extra memory available!L08L7 & & & =Use default config for 0)ȩ = =K? =NL 8 =Size(K)? ? N@FjFjFjFj: =Page sequence? ? P@o* =RAM disk %drive no? = 09) `9 - 9**H***) 9 Ȋ)h9 @@ H'h(#''/'(ɛ ? P@(@: 3 ʽ' L 8 =Duplicated sequence number!L7 =Wrong number of entries!L7K&큅쀄 =Verify WRITEs? ; =Number of File Buffers? ? N@  6 Lv),R( 4;L),Drive number or : =ɛLP99L50Ȍ( =Remove drive? =Y =Is drive configurabl'e? =YЂ =High capacity drive? =Yy =Is drive double sided? =Y *; =Tracks/side? ? N@#0M P( *; =Step rate? =4/ *; 4;L), =Drive size (in sectors)? ? N@H(h 7;L),RAM disk drive no? 8L),Verify (WRITEs? ;L), =WNPp`(`(  LqBSAVE:filename,start,end(,init(,run)) @TUH P@Cp` ?< P@؆8օڊ CInvalid START-END range!۩ P@  P@ hԄՠAλȌZ B04)*  0$ڍXۍY֍T׍U,0LCL C HCL@ֆ׌`Load MEM.SAV from what file? 0#L),L@Load from what file?) @TU&̩Z B &0&-&а&𨭻INIZ'RV0II CNO CARTRIDGE!*Ԇխ  )L>Run from what address? ?ɛ P@ CAddress must be 1-4 hex digits! BHILV {=`hh =HH` =0{a Hɛ {= {=h` {=L), = = pHH =hh`K: p `(+((( i ɀ((L@(`(BD(0>HH''>I>U>I>ɛ(ɛ (>(`͈>DH(` (HI`(k5 = =( 5B( (>@A (J B0}((HHIIDDEE B @(CɈP,(# B = =( 5BL'?(B>>((ڤ ܝHݝI VL>L@(" B !B I)  B(L& R XY( @&:0H&Ϳ((& ( .( & ( .(ʩ(`ލD&ߍEB-IʎH( V0`ԩ ؠA@ȱB@ȱ)C@ CError -- 163&`$8f cAԄձG/ $<68i/(Ԧ`H&եԦ&&eԅheԅԊe(iLZ@&&&&ԅLZ@B ? cA?*(ɛ:./2SX.(0ȱ/.ɛ(ލ8'ި0#:Ȱ :ފ :ȱ: : sAD sAޥ`(eޅީe߅`(` @LA @TUȪ: CFile name not allowed!: )  h( >0+L TUD CNot a disk/ file!(0` =Insert SOURCE disk, press =,(pӮ(A(O aB qBaB`1(L$ b(de BJKO L@O` B((*(((`ȱޙ((:>Ȍ(`D:`OS.0SYS,DOS.SYShh =L),  VLI /C /C,pLhL~F#Խ٩Յ׆  LC`David R. Eichel rel.ver.1/1/90L$ b(de BJKO L@O` B((*(((`ȱޙ((:>Ȍ(`D:`OS.; THIS PROGRAM WRITES A SINGLE FILE TO THE CASSETTE AND IS ; USED IN CONJUNCTION WITH A PROCEDURE TO MAKE CASSETTE ; BOOTABLE FILES. THE FOLLOWING TWO SYMBOLS MUST BE EQUATED ; USING THE MEMORY LIMITS OF THE PROGRAM TO BE COPIED. ; ; 'PST' = PROG2RAM START ADDRESS (SEE SAMPLE PROGRAM) ; 'PND' = PROGRAM END ADDRESS (SEE SAMPLE PROGRAM) ; PST= $08C9 PND= $18F4 FLEN= PND-PST+127/128*128 ; ROUND UP TO MULTIPLE OF 128. *= $B000 ; THIS PROGRAM'S ORIGIN. BOOT3B LDX #$10 ; USE IOCB #1. ; FIRST OPEN THE CASSETTE FILE FOR WRITING. LDA #OPEN ; SETUP FOR DEVICE "OPEN". STA ICCOM,X LDA #OPNOT ; DIRECTION IS "OUTPUT". STA ICAX1,X4 LDA #$80 ; SELECT SHORT IRG. STA ICAX2,X LDA #CFILE ; SETUP POINTER TO DEVICE NAME. STA ICBAL,X LDA #CFILE/256 STA ICBAH,X JSR CIOV ; A5TTEMPT TO OPEN FILE. BMI CERR ; NOW WRITE THE ENTIRE FILE AS ONE OPERATION. LDA #PUTCHR ; SETUP FOR "PUT CHARACTERS". STA ICCOM,X LDA #PST ; POINT TO START OF APPLIC. PROG. ST6A ICBAL,X LDA #PST/256 STA ICBAH,X LDA #FLEN ; SETUP # OF BYTES TO WRITE. STA ICBLL,X LDA #FLEN/256 STA ICBLH,X JSR CIOV ; WRITE ENTIRE FILE. 7 BMI CERR ; ERROR. ; NOW CLOSE THE FILE AFTER SUCCESSFUL WRITE. LDA #CLOSE ; SETUP FOR "CLOSE". STA ICCOM,X JSR CIOV ; CLOSE THE FILE. BMI CERR BRK 8 ; STOP WHEN DONE. CERR BRK ; STOP ON ERROR. CFILE .BYTE "C:",CR ; FILE NAME. ; THIS IS THE CARTRIDGE HEADER *= $BFF9 ; "A" CARTRIDGE. INIT RTS .WORD BOOTB 9 .BYTE 0,5 .WORD INIT .END 3 LIST X .TITLE 'DISK FIXDUMP 2.0, (C) ATARI,INC 10/3/1980' ;DEV =1 ;*IF ENABLED THEN TO LNBUG DEV =0 ;*IF DISABLED THEN TO COLLEEN FIX = 0 ;*CONDITIONAL ASSEMBLY FLAG ;FIX =; 1 ;*FOR FIX NOT FIXDMP CIO = $E456 SIO = $E459 BRKKEY = $11 DOSVEC = $A DVSTAT = $02EA ;*DEVICE STATUS INFO LOCATION DTYMO = $0246 ;*TIMOUT STORAGE FOR DKHND DTYM = < $02EC ;*DISK TIMEOUT STORAGE STAREC = $53 ;*STATUS REQUEST COMMAND BYTE .IF DEV ;*FOR DEVELOPEMENT SYSTEMS FIXORG = $8000 ;* GOES IN CARTRIDGE .ELSE FIXORG = $4000 = ;* GOES IN MEM.SAV REGION .ENDIF .IF FIX .TITLE 'DISK FIXER 1.0, (C) ATARI,INC 1/25/1980' .ELSE .TITLE 'DISK FIXDUMP 2.0, (C) ATARI,INC 1/25/1980' .ENDIF ; ; ; ;**********************************>************************************** ; FILENAME = $MICHAEL.FIXME ;************************************************************************ ;WRITTEN BY IAN SHEPPARD APPROX. MAY 22,1979 ;MODIFIED BY MICHAEL EKBERG MAY 15,1980 TO WORK ON NE?W DOS ;(9/24 MODIFIED) AND TO GIVE SECTOR DUMP AND MODIFY SECTOR ;COPYRIGHT BY ATARI,INC. MAY 15,1980 ;MODIFIED FOR DOS 2.X JULY 1, 1980 *INDICATES MODS. ; ; HILO .MACRO M1 M1&L = .LOW.M1 M1&H = .HIGH.M1 .ENDM ; ; ; ZE@RO PAGE VARIABLES ; *=$18 JMPTBL *=*+2 RAMLO *=*+2 ;*FOR PRINT LINE AFTER MENU CHOICE ;*AND AS INDIRECT PNTR FOR DISK BUFFERS IN EDIT AND DUMP ; *=$2E0 ***RUN ADDRESS*** .WORD DOSOS ; *=FIXORG A ;***ORG TO USER AREA*** DB1 *=*+$80 ;*VOLID BUFFER HILO DB1 PAR *=*+80 PARAMETER AREA HILO PAR LINE *=*+80 TYPEIN LINE BUFFER HILO LINE DB256 *=*+$80 ;*FOR 256 BYTE DEBVICES HILO DB256 DBUF *=*+$80 ;*DISK BUFFER FOR 128 BYTE SECTORS FOR COPY HILO DBUF MENUSZ *=*+1 SECFLG *=*+1 ;*SECTOR SIZE KLUDGE FLAG PER *=*+1 DLENLO *=*+1 ;*LENGTH OCF SECTOR DLENHI *=*+1 ;* DBSTLO *=*+1 ;*START OF SECTOR DUFFER DBSTHI *=*+1 ;*EITHER DBUF OR DB256 TYPSEC *=*+1 ;*IF =$80 THEN SECOND PART OF 256 DISK BUFFER (F CSRC *=*+1 CDDES *=*+1 SAVX *=*+1 PTR *=*+1 IPTR *=*+1 PRINT *=*+2 PRNLEN *=*+2 CTR *=*+1 OPT *=*+1 T1 *=*+2 STVEC *=*+2 A TEMP OF SOME KIND RCNT *=*+1 ;*RETRY COUNT FOR DISK RDM *=*+1 RESHOW MENU FLAG DTH =* E HILO DTH CR = $9B CUP = $1C CDN = $1D CLF = $1E CRT = $1F DLL = $9C CLSCR = $7D ; ; OPEN = $03 CLOSE = $0C PUTCHR = $0A GETCHR = $06 GETRCD = F $04 PUTRCD = $08 RENAME = $20 DELETE = $21 FORMAT = $FE LOCK = $23 UNLOCK = $24 ; TEXT = 1 ; CURFCB = $12E7 ;*CURRENT FCB VALUE STORE DRVTBL = $12F7 ;*DRIVE TABLGE TO TELL IF 128 OR 256 BYTE DEVICE ;*DRVTBL,X=0 :DRIVE X NOT THERE ;* ' =1 :DRIVE X IS 128 BYTE SECTOR ;* ' =2 :DRIVE ; DCB = $300 DUNITH = DCB+1 DCOMND = DCB+2 DSTATS = DCB+3 DBUFLO = DCB+4 DBUFHI = DCB+5 DCBTO = DCB+6 ;*DISK TIMEOUT FOR SIO CALL DCBCNT = DCB+8 ;*DISK BYTE COUNT DSLO = DCB+$A DSHI = I DCB+$B ; IOCB = $340 ICHID = IOCB+0 ICDNO = IOCB+1 ICCOM = IOCB+2 ICSTA = IOCB+3 ICBAL = IOCB+4 ICBAH = IOCB+5 ICBLL = IOCB+8 ICBLH = IOCB+9 ICAX1 = IOCB+10 ICAX2 = J IOCB+11 ; ; ; KDN .BYTE 'K:',CR HILO KDN ; ; ; ; ; INITIALIZE ; DOSOS LDA #$FF STA BRKKEY JSR INITIO CLOSE FILES LDA #OPEN STA ICCOM+$30 K: IOCB LDX #$30 K K: IOCB LDA #$4 STA ICAX1,X OPEN READ LDA #KDNH STA ICBAH,X LDA #KDNL STA ICBAL,X JSR CIO OPEN K: ; ; ; JMP VERDSK .PAGE ; ; VECTOR TO RLOUTINE SELECTED FROM MENU. ; SHMEN LDA PRINT STA ICBAL DISPLAY MENU THRU IOCB0 LDA PRINT+1 STA ICBAH LDA PRNLEN STA ICBLL LDA PRNLEN+1 STA ICBLH JSR MDSPMSG LDA #0 STA RDM JUST SHOWED MENU SO DONT RESHOW MENUSL LDX #$FF TXS BIT RDM BMI PSMEN IF SHOW MENU FLAG SET GO DO IT LDA #BLNKL ;*OUT A BLANK LINE LDX N #BLNKH JSR DSPLIN LDA #SITL SELECT ITEM MESSAGE LDX #SITH JSR DSPLIN JSR CHRGET GO GET KEYBOARD CHAR. CMP #CR ; BNE MENU1 JMP SHMEON MENU1 SEC SBC #'A CONVERT ASCII CHAR. TO BINARY # & SUBTRACT 1. BMI RANGE IF ASCII CHAR NOT A #, GO READ AGAIN CMP MENUSZ IS THE # ENTERED > MENU SIZE? BPL RANGE P IF YES, GO READ AGAIN. ASL A TAY SET INDEX TO (MENU # - 1) * 2 LDA (JMPTBL),Y INY STA RAMLO GET STRING POINTER LDA (JMPTBL),Y STA RAMLO+1 LDY Q #1 LOAD STRING POINTER INTO REGISTERS LDA (RAMLO),Y FOR DSPLIN TAX DEY LDA (RAMLO),Y JSR DSPLIN PRINT MODULES INITIAL STRING LDA RAMLO INC BY 2 TO POINT PAST STRING POINTER R CLC ADC #2 STA RAMLO LDA RAMLO+1 ADC #0 CARRY STA RAMLO+1 PUT HI BYTE. JMP (RAMLO) JUMP TO ROUTINE SELECTED BY MENU. RANGE LDA #NSIL LDX S #NSIH JSR DSPLIN NO SUCH ITEM MESSAGE JMP MENUSL NSI .BYTE 'NO SUCH ITEM',CR HILO NSI ;*THIS IS 'SELECT ITEM OR RETURN FOR MENU' ;* RETURN IS INVERSE VIDEO SITT .BYTE 'SELECT ITEM OR ',$D2,$C5,$D4,$D5,$D2,$CE,' FOR MENU',CR HILO SIT ; ; ; PAUSE AND RESHOW MENU ; PSMEN LDA #0 STA ICBLH LDA #20 STA ICBLL LDA #PMESH STA ICBAH U LDA #PMESL STA ICBAL JSR DSPMSG JSR CHRGET JMP SHMEN PMES .BYTE CR,'HIT ANY KEY TO EXIT' HILO PMES ; ; .PAGE ; ; ; VERIFY/FIX DISK ROUTINE ; ;************** .IF V FIX VERMN .BYTE CLSCR,'DISK FIXER 1.0SD (C) ATARI 10/3/1980',CR .BYTE 'WRITTEN BY M. EKBERG',CR,CR .BYTE 'A: DIRECTORY ENTRIES ',CR .BYTE 'B: TRACE SECTOR CHAIN ',CR .ELSE VERMN .BYTE CLSCR,'FIXDUMP 2.0WSD (C) ATARI 10/3/1980',CR .BYTE 'INTERNAL USE ONLY',CR,CR .BYTE 'A: DIRECTORY ENTRIES H: DUMP SECTORS',CR .BYTE 'B: TRACE SECTOR CHAIN I: EDIT SECTOR',CR .ENDIF .BYTE 'C: MODIFY DIRECTORY ENTRY',CR X .BYTE 'D: CHECK ALLOCATION MAP',CR .BYTE 'E: MODIFY SECTOR LINK',CR .BYTE 'F: SET DRIVE NUMBER',CR .BYTE 'G: EXIT TO DOS',CR .BYTE CDN,CDN,CDN,CDN,CDN VERLN = *-VERMN .IF FIX VERJ Y.WORD DDNT,TSC,MDE,CAM,MSL,SDN,EXVD .ELSE VERJ .WORD DDNT,TSC,MDE,CAM,MSL,SDN,EXVD,HEXDMP,EDSEC .ENDIF HILO VERJ HILO VERMN HILO VERLN .IF FIX MENN = 7 .ELSE MENN = Z 9 .ENDIF VERDSK LDA #1 JSR SETIO LDA #VERMNL SET UP MENU PARAMETERS STA PRINT LDA #VERMNH STA PRINT+1 LDA #VERLNL STA PRNLEN LDA #VERLNH [ STA PRNLEN+1 LDA #MENN STA MENUSZ LDA #VERJL STA JMPTBL LDA #VERJH STA JMPTBL+1 JMP SHMEN GO SHOW MENU AND SELECT. ; ; SET DRIVE NUMBER ; SDN .WOR\D SDMN JSR GETLIN LDA LINE ; CMP #CR BNE SDN1 ;*USER HIT CR? LDA #DRVMSL LDX #DRVMSH JSR DSPLIN JMP MENUSL SDN1 JSR ] GETNO JSR PERX JSR SETIO JMP MENUSL SDMN .BYTE 'USE WHAT DRIVE NUMBER?',CR DRVMS .BYTE 'WRONG DRIVE NUMBER',CR HILO DRVMS ;SET UP FOR SIO CALL ; SETIO CMP #$09 ;CHECK IF NUMBER <^9 BCS NODRIVE ;*NO EXIT STA UNNO ;*SAVE DRIVE # STA DUNIT ;*PUT # IN DCB LDA #7 ;*7 STORE TIMEOUT VALUE STA DCBTO LDA #4 ;*SET_ LENGTH =4 STA DCBCNT ;* LDA #0 ;* STA DCBCNT+1 ;* LDA #2 ;*SET BUFFER ADDRESS STA DBUFHI ;*LO LDA #$EA ;*LO ` STA DBUFLO ;* LDA #STAREC ;*SET FOR STATUS REQUEST LDY #$40 ;*SET FOR RECEIVE JSR CLDKH ;*GET STATUS OF THIS DEVICE LDY DTYM ;*GET TIMEOUT RETURNEaD STY DTYMO ;*SAVEIT LDY #0 ;ASSUME 128 BYTE DEVICE LDA DVSTAT ;GET STATUS BYTE AND #$20 ;*IS IT 128 OR 256 BYTE DRIVE BEQ SET1 ;128? Y IS bSET ALREADY LDY #1 ;ELSE SET FOR 256 BYTE DRIVE SET1 STY DLENHI BEQ SD128 LDX #DB256H ;*256 BYTE SECTOR BUFFER LDY #DB256L LDA #0 ;*LENGTH IS 256 BYTES cFOR SIO CALL STA DLENLO BEQ SEXIT SD128 LDA #$80 ;*128 BYTE SECTOR LENGTH STA DLENLO ;*START OF 128 BYTE SECTOR LDX #DBUFH LDY #DBUFL SEXIT STY DBSTLO ;d*STORE START OF BUFFER (128 OR 256) STX DBSTHI RTS ;*EXIT NODRIVE LDA #NDRMSL ;*HERE IF DRIVE NOT CONNECTED LDX #NDRMSH ;*PRINT MESSAGE TO THAT EFFECT JSR DSPLINe JMP MENUSL .PAGE NDRMS .BYTE 'DRIVE NOT CONNECTED',CR ;* HILO NDRMS ; ; MODIFY SECTOR LINK ; MSL .WORD MSLM JSR GETLIN JSR GETNO JSR PERX STX DSHI f STA DSLO POINT TO THE SECTOR PHA TXA SAVE THEM FOR LATER PHA JSR FDSEC SHOW IT JSR DSPLIN LDA #16 STA ICBLL LDA #0 STA ICBLH DO CgURSOR UP AND LDA #MLML POSITION TO FIRST DATA FIELD STA ICBAL LDA #MLMH STA ICBAH JSR DSPMSG JSR CIOGET GET LINE FROM SCREEN EDITOR LDA #', STA LINE+17 TEhRMINATE FP FIELD FOR GETNO LDA #0 STA PER SET UP FOR GETNO CALLS STA IPTR JSR GETNO FILE NUMBER ASL A ASL A STA DBUF+125 LDA #7 STA IPTR i JSR GETNO REL SEC NUM TO A BPL *+4 ORA #$80 STA DBUF+127 ;STORE # OF BYTES IN SECTOR LDA #14 STA IPTR JSR GETNO FORWARD POINTER STA DBUF+126j TXA ORA DBUF+125 STA DBUF+125 LDX LINE+18 CPX #'E ;IS EOF? BNE SKP1 ; NO. SKIP JSR SETEOF ; YES. SET FORWARD POINTER TO ZERO(EOF) SKP1 PLkA GET SECTOR NUMBER BACK STA DSHI (FDSEC POINTS DCB TO NEXT ONE) PLA STA DSLO JSR DKWRT JMP MENUSL MSLM .BYTE 'MODIFY LINK OF WHAT SECTOR?',CR MLM .BYTE CUP,CRT,CRT,CRT,CRlT,CRT,CRT,CRT,CRT .BYTE CRT,CRT,CRT,CRT,CRT,CRT,CRT HILO MLM ; ; ; DDNT - DISPLAY DIRECTORY ENTRIES ; DDNT .WORD DNMG JSR GETLIN JSR GETNO STA DENO JSR GETNO GET 2ND PARAM m CMP #65 ;*TEST FOR 64 DIRECTORY ENTRIES BCC DDNT1 ;* LDA #64 ;* DDNT1 STA SCNO JSR PERX LDA #DDHL LDX #DDHH JSR DSPLIN LDA n #$FF STA DSHI MAKE SECTOR NO INVALID SNE JSR SDE SHOW THIS ENTRY JSR DSPLIN INC DENO NEXT LDA SCNO CMP DENO BPL SNE SHOW NEXT ENTRY UNLESS DONE DDNTX JMP o MENUSL EXIT. DDH .BYTE 'D# FILENAM EXT FSEC #SEC DL',CR HILO DDH DNMG .BYTE 'FIRST,LAST DIR ENTRIES TO SHOW?',CR ; ; ; ; MDE - MODIFY DIRECTORY ENTRY ; MDE .WORD MDMG JSR GETLIN JSR GETNO STpA DENO NOTE DIR ENTRY TO CHANGE JSR PERX LDA #DDHL LDX #DDHH JSR DSPLIN DIR ENTRY HEADER(TEMPLATE) LDA #$FF STA DSHI NO SECTOR IN BUFFER JSR SDE FORMAT ENqTRY FOR DISPLAY JSR DSPLIN SHOW THE LINE LDA #0 STA ICBLH LDA #4 STA ICBLL SET UP DSPMSG FOR A CUP(CURSOR UP) LDA #DCUPL STA ICBAL LDA #DCUPH STA r ICBAH JSR DSPMSG GO DO THE CUP LDA #0 STA LINE+22 CLEAR ANY JUNK FROM BEFORE STA LINE+23 JSR CIOGET GET LINE FROM SCREEN EDITOR LDA #', INSERT COMMAS FOR GETNOS SAKE s STA LINE+16 STA LINE+21 AFTER HEX NUMBERS LDX SAVX GET DIR ENTRY OFFSET BACK FROM SDE LDY #0 CMFN LDA LINE+0,Y STA DB256+5,X INX INY CPY #11 BNE CMFtN LDA #12 SET UP FOR GETNO STA IPTR LDA #0 STA PER SET NO PARAM ERRORS FOR GETNO JSR GETNO LDX SAVX STA DB256+3,X LDA T1 STA DB256+4,X u JSR GETNO LDX SAVX STA DB256+1,X LDA T1 GETNO ALSO PUTS NUMBER IN T1,T1+1 STA DB256+2,X JSR PERX IF GETNO DETECTED ERRORS, EXIT LDX LINE+22 D GOES HERE FOR DELETE v LDA #$40 FLAG BYTE CPX #'D BNE *+4 ORA #$80 DELETE BIT LDX LINE+23 CPX #'L LOCK BNE *+4 ORA #$20 LOCK BIT LDX SAVX STA DwB256,X ; REWRITE THE SECTOR LDA UNNO STA DUNIT JSR DKWRT GO DO IO ; REALLY SHOULD CHECK FOR ERRORS HERE JMP MENUSL DONE. MDMG .BYTE 'WHICH ENTRY TO MODIFY?',CR DCUP .BYTE CUP,CRT,CRT,CRT x HILO DCUP ; ; TSC - TRACE SECTOR CHAIN ; TSC .WORD TSMG LDA #$FF STA BRKKEY STA DSHI MAKE SECTOR NO INVALID JSR GETLIN JSR GETNO STA DENO JSR PERX y JSR SDE SHOW THE ENTRY JSR DSPLIN ;SECTOR WITH DIRECTORY INFO IS NOW IN BUFFER. READ FIRST SECTOR LDX SAVX GET DIR ENTRY OFFSET FROM SDE LDA DB256+3,X GET START SECTOR STA DSLO LzDA DB256+4,X STA DSHI NXCHN JSR FDSEC JSR DSPLIN LDA DBUF+125 LSR A LSR A FILE NUMBER CMP DENO BNE BLK IF BAD LINK JSR TSTEOF ;I{F NOT EOF BNE NXCHN ; THEN JMP***************** JMP MENUSL EXIT BLK LDA #BLL LDX #BLH JSR DSPLIN JMP MENUSL TSMG .BYTE 'TRACE FROM WHAT DIR ENTRY?',CR BL .BYTE 'B|AD LINK',CR HILO BL EXVD .WORD EXVDM JMP (DOSVEC) EXVDM .BYTE CR ; ; ; DATA ; DENO *=*+1 SSEC .BYTE 'SECTOR ' SNO *=*+3 .BYTE ': F#=' FNO *=*+2 .BYTE ', BS=' RNO *=*+2 .BYTE} ', FP=' FPT *=*+3 .BYTE ' ' EFG *=*+1 .BYTE CR SCNO *=*+1 UNNO *=*+1 HILO SSEC ; ; CAM - CHECK ALLOCATION MAP ; ; CREATE BITMAP OF ALLOCATED SECTORS. COMPARE TO MAP ON ; FMS VTOC SECTOR. SHOW D~IFFERENCES ; ; CAM .WORD CAMG ;INITIALIZE MAP AT PAR TO PAR+$59 JSR VTOCS ;*GET VOLUME ID SECTOR IN DB1 JSR RSEC1 LDX #$59 LDA #$FF STA PAR,X DEX BPL *-4  LDA #$7F STA PAR+$2E VTOC SECTOR LDA #0 STA PAR+$2D DIRECTORY SECTORS LDY #$0F LDA DB1 ;*GET FIRST BYTE OF VOLID CMP #2 ;*CHECK FOR DOS II BEQ CAM2 LDY #$3F CAM2 STY PAR BOOT SECTOR (SECTOR 1) ;FOR EACH FILE, MARK SECTORS AS IN USE LDA #0 STA DENO PNDE LDA #$FF STA DSHI FOR FDE ;READ THIS DIR ENTRY JSR FDE LDA DB256,X IF NOT IN USE OR DELETED, SKIP IT. BPL *+5 JGNDE JMP GNDE AND #$40 BNE *+5 JMP RVB LDA DB256+1,X ZERO LENGTH FILE ORA DB256+2,X IS TREATED AS DELETED BEQ JGNDE LDA DB256+3,X STA DSLO LDA DB256+4,X STA DSHI JSR SETEOF ;SET FORWARD PNTR TO ZERO(EOF) ;READ AND MARK IN USE NEXT SECTOR LTNS LDA DSHI STA T1+1 LDA DSLO STA T1 LDA DSLO IF POINTING TO SECTOR ZERO ORA DSHI MUST BE A BAD LINK BEQ SBL JSR RSEC LDA DBUF+125 AND #3 GET FORWARD POINTER SEC NO STA DSHI INTO DCB LDA DBUF+126 STA DSLO LDA DBUF+125 LSR A LSR A GET FILE # CMP DENO BEQ MSIU IF FILE# MISMATCH SBL LDA DENO JSR ASCCON STX BLN STA BLN+1 LDX #BLMH LDA #BLML JSR DSPLIN JMP GNDE ;MARK SECTOR IN USE MSIU LDA T1 AND #$7 PHA SHIFT COUNT LSR T1+1 3 BIT SHIFT OF 2 BYTES ROR T1 LSR T1+1 ROR T1 LSR T1 ALL BITS ARE IN ONE BYTE BY NOW PLA TAX LDA #$7F MASK TO SHIFT NXSC DEX BMI EXS SEC ROR A BNE NXSC EXS LDX T1 AND PAR,X STA PAR,X ;SEE IF EOF JSR TSTEOF ;IF NOT EOF THEN BNE LTNS ;JMP TO LTNS GNDE INC DENO NEXT DIR ENTRY LDA DENO CMP #$40 BPL RVB IF ALL DIR ENTRIES ARE DONT JMP PNDE ELSE DO NEXT ONE ;ALLOCATION MAP IS ALL DONE ;COMPARE THE TWO MAPS, DB1 IS ORIGINAL MAP RVB LDX #0 STX OPT FLAG NO DIFFERENCES STX SAVX CMB LDX SAVX LDA PAR,X BYTE OF BUILT MAP CMP DB1+10,X BYTE OF VTOC MAP BNE FMDF IF FOUND DIFFERENCE CMC INC SAVX LDX SAVX CPX #$5A BNE CMB LDA OPT SEE IF DIFFERENCES BPL CAMX NO, EXIT LDA #RWL QUERY TO REWRITE MAP LDX #RWH JSR DSPLIN JSR CHRGET CMP #'Y BNE CAMX ;REWRITE MAP LDX #$59 MMP LDA PAR,X GENNED MAP STA DB1+10,X MAP IN VTOC SECTOR BUFFER DEX BPL MMP JSR VTOCS POINT TO VTOC JSR DKWRT WRITE IT CAMX JMP MENUSL ALL DONE. ;FOUND MAP DIFFERENCE ;FIND DIFFERING BITS, SHOW SECTORS FMDF LDA #$80 BIT TO CHECK STA OPT FLAG DIFFERENCES FOUND STA CSRC LDA #0 STA CDES SHIFT COUNT FMDF1 LDX SAVX LDA PAR,X EOR DB1+10,X AND CSRC BIT COMPARE BNE FDB IF FOUND DIFFERENT BIT NXBM INC CDES LSR CSRC MOVE TEST BIT BCC FMDF1 TRY AGAIN UNLESS BIT HAS WANDERED OUT BCS CMC ;FOUND DIFFERENT BIT. SHOW SECTOR, HOW MARKED FDB LDA DB1+10,X AND CSRC SEE WHAT VTOC SAYS ABOUT THIS SECTOR STA PER SAVE THE BIT STX DSLO LDA #0 STA DSHI CREATE SECTOR NO FROM BYTE INDEX, SHIFT CT ASL DSLO ASL DSLO ROL DSHI ASL DSLO ROL DSHI LDA CDES ORA DSLO STA DSLO HAVE SECTOR NO IN DCB NOW ;DCB NOW POINTS TO SECTOR JSR FDSEC FORMAT FOR DISPLAY JSR DSPLIN SHOW IT LDA PER BEQ MAL MARKED ALLOCATED LDX #MFMH LDA #MFML FDB1 JSR DSPLIN JMP NXBM MAL LDX #MAMH LDA #MAML BNE FDB1 ; ; VTOCS - POINT TO VTOC SECTOR AND BUFFER. VTOCS LDA #DB1H STA DBUFHI LDA #DB1L STA DBUFLO SET DCB TO POINT TO DB256+$80 LDA #1 STA DSHI LDA #$68 STA DSLO VTOC SECTOR NUMBER RTS .PAGE CAMG .BYTE 'BUILDING ALLOCATION MAP...',CR BLM .BYTE 'BAD LINK IN FILE # ' BLN *=*+2 .BYTE CR RW .BYTE 'TYPE ',$22,'Y',$22,' TO REWRITE ALLOCATION MAP',CR HILO BLM HILO RW MAM .BYTE 'WAS MARKED IN USE',CR MFM .BYTE 'WAS MARKED FREE',CR HILO MAM HILO MFM BLNK .BYTE ' ',CR HILO BLNK MSCUP .BYTE CUP,CUP,CR HILO MSCUP BYMSG .BYTE 'BYTE',CR HILO BYMSG HEXMSG .BYTE 'ENTER START,END(HEX) SECTORS TO DUMP',CR BUFA .BYTE ' ' BUFB .BYTE 'XX XX XX XX XX XX XX XX' .BYTE ' ' BUFC .BYTE 'XXXXXXXX',CR HILO BUFA ; BCNTR *=*+1 AIND *=*+1 ;INDEX FOR BUFB(HEX DIGIT BUFFER SAVY *=*+1 BIND *=*+1 TOPLO *=*+1 TOPHI *=*+1 JUMP *=*+2 ;INDIRECT JUMP ADDRESS REG2 =JUMP ; ; HEXDMP .WORD HEXMSG JSR EDGET ;*GET START SECTOR IN DSHI,DSLO JSR GETNO ;GET LAST SECTOR NUMBER JSR PERX ;TEST FOR ERROR STX TOPHI ;STORE IT STA TOPLO ; NEXTSC JSR SECHCK ;*CHECK IF SECTOR IS 1-3 ON 256 BYTE LDA #0 STA TYPSEC ;*SET TO FIRST DSPLAY CALL JSR DSPLAY LDA DLENHI BEQ HEX1 ;*IF 128 BYTE SECTOR JMP LDA #$80 ;*ELSE DO SECOND PART OF 256 SECTOR STA TYPSEC JSR DSPLAY HEX1 INC DSLO BNE HEX2 INC DSHI HEX2 LDA DSHI ;*DONE? CMP TOPHI BCC NEXTSC BNE DOUT LDA TOPLO CMP DSLO BCS NEXTSC DOUT LDA #MSCUPL ;*CURSOR UP LDX #MSCUPH JSR DSPLIN JMP MENUSL ;ELSE DONE EXIT ; PLXY PLA ;SET UP RETURN ADDRESS STA JUMP INC JUMP ;BUMP RETURN ADDRESS 1 PLA STA JUMP+1 PLA ;PULL Y,X,A TAY PLA TAX JMP (JUMP) ;RETURN TO CALLER ; PHXY PLA ;SET UP RETURN ADDRESS STA JUMP PLA STA JUMP+1 INC JUMP ;INC PC TO RETURN ADDRESS TXA PHA TYA PHA JMP (JUMP) ;RETRUN TO CALLER ; DSPLAY LDX DLENHI ;*TEST IF DEVICE IS 128 OR 256 BEQ DS1 ;*IF 0 THEN 128 BYTE LDA TYPSEC ;*ELSE 256.IF TYPSEC=$80 THEN SECOND PART OF BNE DS1 ;*BUFFER LDX #DB256L ;*SET FOR FIRST 1/2 OF BUFFER (256) LDY #DB256H JMP DS2 DS1 LDX #DBUFL ;*SET FOR SECOND 1/2 OF BUFFER (256) LDY #DBUFH ;*OR 128 BUFFER DS2 STX RAMLO ;*INDIRECT FOR DISK BUFFERS STY RAMLO+1 ;* LDA DSLO ;*SAVE SEC NUMS PHA LDA DSHI PHA LDA TYPSEC ;*IS IT SECOND PART OF 256? BEQ DS3 ;*NO JSR FDSEC1 ;*YES SET UP DISPLAY JMP DS4 ;*SKIP DS3 JSR FDSEC ;GET SECTOR AND SET UP DISPLAY DS4 JSR DSPSEC ;DISPLAY SECTOR DUMP PLA STA DSHI ;*RESTORE SEC NUM PLA STA DSLO RTS DSPSEC JSR DSPLIN ;SHOW SECTOR INFO LDA #BYMSGL ;WRITE BYTE LDX #BYMSGH JSR DSPLIN LDA #4 ;SET LINE COUNTERS LDY #0 ;DISK BUFFER INDEX(DBUF) STY BCNTR ;BYTE COUNT STY AIND ;DBUF INDEX TAY ;SET OUTER(4X4)LINE COUNTER TAX ;SET INNER 4 LINE INDEX DONEXT JSR DOLINE ;WRITE 8 BYTES DEX ;DONE WITH 4 LINES? BNE DONEXT ;NO. LDX #4 ;REST INNER 4 LINE COUNT JSR SCROL1 ;PUT IN A BLANK LINE DEY ;DONE WITH 16 LINES? BNE DONEXT ;NO. RTS ; SCROL1 JSR PHXY ;SAVE REGS LDA #BLNKL ;WRITE BLANK LINE LDX #BLNKH ; JSR DSPLIN ; JSR PLXY ;EXIT RTS ; PUTVAL LDA BCNTR ;WRITE BYTE COUNT TO LINE CLC ;* ADC TYPSEC ;*ADD $80 IF SECOND PART OF 256 BYTE SECTOR JSR ASCCON ;CONVERT TO ASCII STX BUFA ;STORE HIGH IN OUTPUT BUFFER STA BUFA+1 ;STORE LO RTS ;* ;* ROUTINE TO GET BYTE FROM DISK BUFFER ;* GETBYT STY REG2 LDY AIND ;*SET BUFFER INDEX FOR INDIRECT LDA (RAMLO),Y LDY REG2 RTS ; DOLINE JSR PHXY ;SAVE Y,X,A JSR PUTVAL ;WRITE BYTE COUNT TO SCREEN LDY #0 STY BIND ;INDEX TO ASCII BUFFER D1 JSR GETBYT ;*GET NEXT BYTE IN DISK BUFFER INC AIND ;BUMP DBUF POINTER PHA ;SAVE CHAR CMP #$20 ;TEST TO SEE IF BYTE IS BAD ASCII BCC SETX ;YES. CMP #123 ;BAD? BCC D2 ;NO. SETX LDA #46 ;YES. SET TO PERIOD D2 LDX BIND ;BIND IS INDEX TO ASCII OUT BUFFER STA BUFC,X ;STORE ASCII IN OUT BUFF PLA ;GET ASCII BYTE TO CONVERT JSR ASCCON ;CONVERT ASCII BYTE TO 2 HEX STA BUFB+1,Y ;STORE HIGH BYTE TXA STA BUFB,Y ;STORE LO HEX BYTE INY INY INY INC BCNTR ;BUMP BYTE COUNTER INC BIND ;INC BYTE COUNTER LDA #8 ;8 BYTES? CMP BIND ; BNE D1 ;NO. LDA #BUFAL ;SET UP TO OUTPUT LINE LDX #BUFAH JSR DSPLIN ;OUTPUT THIS LINE JSR PLXY ;YES. EXIT RTS ; ; EDIT A SECTOR ON DISK ; CLMS .BYTE CLSCR,CR HILO CLMS EDMSG .BYTE 'ENTER HEX DISK SECTOR TO EDIT',CR EDMS .BYTE 'TYPE ',$22,'Y',$22,' TO WRITE SECTOR',CR HILO EDMS EDM2 .BYTE 'TYPE ',$22,'Y',$22,' TO EXIT',CR HILO EDM2 .PAGE EDM3 .BYTE 'ENTER HEX SECTOR TO WRITE BUFFER TO',CR HILO EDM3 ED11 .BYTE CUP,'TYPE BRK TO EXIT',CR HILO ED11 ; EDSEC .WORD EDMSG ;EDIT MESSAGE LDA #0 ;*SET DBUF FLAG TO START STA TYPSEC ;* JSR EDGET ;GET SECTOR NUMBER TO EDIT ED0 JSR DSPLAY ;DISPLAY SECTOR IN DISK BUFFER LDA #ED11L ;*PRINT 'HIT BREAK TO EXIT' LDX #ED11H ;* JSR DSPLIN ;* ED3 JSR CIOGT1 ;GET A LINE OF SCREEN CPY #$80 ;ON BREAK KEY BEQ EDEX ;EXIT THIS ROUTINE LDX #0 ;INDEX TO CURRENT LINE JSR CNVERT ;GET BYTE COUNT THIS LINE INX TAY ;SET INDEX TO DBUF TO BYTE COUNT ED2 JSR TSTEND ;*IS INDEX OF DBUF OUT OF BOUNDS BCS ED1 ;YES. DISPLAY SECTOR JSR CNVERT ;NO. CONVERT NEXT 2 HEX TO 1 ASCII JSR STASH ;STORE IN DISK BUFFER INY ;BUMP DBUF INDEX CPX #27 ;DONE WITH LINE? BCC ED2 ;NO. DO ANOTHER BYTE ED1 LDA #CLMSL ;CLEAR SCREEN LDX #CLMSH JSR DSPLIN LDA DSLO ;*SAVE SEC NUMS PHA LDA DSHI PHA JSR FDSEC1 ;DISLAY SECTOR INFO JSR DSPSEC ;DUMP SECTOR PLA STA DSHI ;*RESTORE SEC NUM PLA STA DSLO JMP ED3 ;ALWAYS JUMP ; EDPR LDA #EDMSL ;WRITE SECTOR? MESSAGE LDX #EDMSH JSR DSPLIN JSR CHRGET ;GET A CHAR CMP #'Y ;IS IT A Y? RTS EDEX LDA DLENHI ;*IF 128 BYTE DEVICE THEN BEQ EDEX2 ;*THEN DONE LDA TYPSEC ;*IF TYPE <>0 THEN DONE WITH EDIT BNE EDEX2 ;*IF TYPE <>0 THEN DONE WITH THIS SECTOR LDA #$80 ;* STA TYPSEC ;* JMP ED0 ;* EDEX2 JSR EDPR ;PRINT MESSAGE AND GET RESULT BNE ED5 ;NO. EXIT EDEX1 JSR DKWRT ;YES. WRITE OUT THIS SECTOR TO DISK EDOUT JMP MENUSL ;BOOGIE ; CNVERT LDA LINE,X ;GET FIRST BYTE OF HEX IN LINE JSR HEXCON ;CONVERT TO NIBBLE BMI ED1ERR ;ON ERROR.EXIT ASL A ;SHIFT LEFT NIBBLE ASL A ASL A ASL A STA SAVY ;SAVE IT TO PACKIT INX ;BUMP LINE POINTER LDA LINE,X ;GET NEXT BYTE INX INX ;BUMP PNTR PAST SPACES IN LINE JSR HEXCON ;NIBBLE IT BMI ED1ERR ;EXIT ON ERROR ORA SAVY ;PACK THE NIBBLES RTS ; ED1ERR PLA ;POP STACK TO RETURN PLA ; JMP ED1 ;RESHOW SECTOR ; ED5 LDA #EDM2L ;EXIT? LDX #EDM2H JSR DSPLIN JSR CHRGET ;GET ANSWER CMP #'Y BEQ EDOUT ;YES. EXIT LDA #EDM3L ;WRITE TO DIFFERENT SECTOR THAN READ? LDX #EDM3H ; JSR DSPLIN LDA SECFLG ;*SAVE SECTOR FLAG PHA JSR EDGET PLA CMP SECFLG BNE EDCANT ;*IF SECTOR ARE DIFERENT SIZE JSR EDPR ;ASK TO WRITE SECTOR BEQ EDEX1 ;YES GO WRITE IT BNE ED5 ;NO. ASK TO EXIT EDCANT STA SECFLG ;*SAVE OLD FLAG LDA #EDMS4L LDX #EDMS4H JSR DSPLIN ;*SAY CANT WRITE TO THAT SECTOR JMP ED5 ;*TRY AGAIN ; EDGET JSR GETLIN ;GET SECTOR NUMBER JSR GETNO JSR PERX ;ON ERROR RETURN TO MENUSL STX DSHI STA DSLO SECHCK LDA #1 STA SECFLG ;*NORMAL SECTOR FLAG LDA UNNO JSR SETIO LDA DLENHI BEQ EDSEX LDA DSHI BNE EDSEX LDX DSLO CPX #4 BCS EDSEX LDY #0 STY SECFLG JSR SET1 EDSEX RTS EDMS4 .BYTE 'CANNOT WRITE TO THAT SECTOR.' .BYTE 'SECTOR SIZE MISMATCH',CR HILO EDMS4 ; ; ;*SUBROUINE TO PUT DATA IN DISK BUFFER ; STASH PHA ;*SAVE IT LDA DLENHI ;*IS IT 128 OR 256 BEQ ST128 PLA STA DB256,Y RTS ST128 PLA STA DBUF,Y RTS ; ; ; ; ; ; SUBROUTINES ; ; ; FDSEC - FORMAT SECTOR WHOSE # IS IN DCB FOR DISPLAY. ; RETURN WITH (A,X)=POINTER TO DISPLAY LINE. ; FDSEC JSR RSEC GO READ A SECTOR FDSEC1 LDA DSHI JSR ASCCON TO DISPLAY STA SNO LDA DSLO JSR ASCCON STX SNO+1 STA SNO+2 LDA DBUF+125 GET FILE # LSR A LSR A JSR ASCCON CONVERT FILE # STX FNO STA FNO+1 LDA DBUF+127 RELATIVE SECTOR AND #$7F JSR ASCCON STX RNO STA RNO+1 LDA DBUF+125 AND #$3 STA DSHI JSR ASCCON STA FPT FORWARD POINTER LDA DBUF+126 STA DSLO JSR ASCCON STX FPT+1 STA FPT+2 LDX #'E JSR TSTEOF ;IF EOF THEN BEQ SKP3 ; SKIP LDX #' SKP3 STX EFG LDA #SSECL LDX #SSECH RTS ; ; ; SDE - SHOW DIRECTORY ENTRY WHOSE # IS IN DENO ; SDE JSR FDE FIND DIR ENTRY LDA DENO JSR ASCCON STX LINE STA LINE+1 LDA #' LDX #27 BLLIN STA LINE+2,X DEX BPL BLLIN LDY #0 LDX SAVX MFN LDA DB256+5,X MOVE FILENAME TO LINE+3 BUFFER STA LINE+3,Y INX INY CPY #11 BNE MFN LDX SAVX LDA DB256+4,X START SECTOR HI JSR ASCCON STX LINE+15 STA LINE+16 LDX SAVX LDA DB256+3,X START SECTOR LO JSR ASCCON STX LINE+17 STA LINE+18 LDX SAVX LDA DB256+2,X JSR ASCCON STX LINE+20 STA LINE+21 LDX SAVX LDA DB256+1,X JSR ASCCON STX LINE+22 STA LINE+23 LDX SAVX LDA DB256,X FLAG BPL NODEL IF NO DELETE LDY #'D STY LINE+25 NODEL AND #$20 LOCK BEQ NOLOC IF NO LOCK LDA #'L STA LINE+26 NOLOC LDA #CR STA LINE+27 LDA #LINEL LDX #LINEH RTS ; ; FDE - FIND DIR ENTRY ; TAKE DIR ENTRY # FROM DENO. FIND SECTOR # AND OFFSET. ; NOTE THAT THIS ROUTINE ASSUMES THAT THE SECTOR POINTED ; TO IN DCB (DSLO,DSHI) HAS ALREADY BEEN READ FROM DISK. ; IF NOT STORE FF IN DSHI TO FOOL IT. SETS SAVX TO OFFSET ; FDE LDA DENO LSR A LSR A LSR A CLC ADC #105 LOW BYTE DIR START SECTOR STA T1 LDA #1 ADC #0 CARRY STA T1+1 CMP DSHI SEE IF WE HAVE THE SECTOR WE NEED BNE NMAT LDA T1 CMP DSLO BEQ GOTIT NMAT LDA T1 STA DSLO LDA T1+1 STA DSHI JSR RSEC GO READ NEEDED SECTOR GOTIT LDA DENO AND #7 DIR ENTRY POSITION IN SECTOR ASL A ASL A ASL A ASL A TAX LDX DLENHI ;*IS IT 128? DIR ENTRY BNE FDERTS ;*NO INDEX IS TO DB256 ORA #$80 ;*ELSE INDEX IS TO DBUF FDERTS TAX ;*SAVE INDEX TO DISK BUFFER STX SAVX RTS ; ; RSEC - READ A SECTOR WHOSE NUMBER IS IN DCB ; RSEC LDA DBSTLO ;*PUT START OF DISK BUFFER IN DCB STA DBUFLO LDA DBSTHI ;* STA DBUFHI RSEC1 LDA UNNO STA DUNIT LDA #$52 GET SECTOR LDY #$40 ;*SIO READ COMMAND JMP CLDKH ; ; DKWRT - WRITE A SECTOR, NUMBER IN DCB ; DKWRT LDA #$57 LDY #$80 ;*SIO WRITE COMMAND CLDKH STA DCOMND LDA #2 ;*SET RETRY COUNT STA RCNT ;*STORE IT CLD1 JSR DKHND CMP #1 ;*IS STATUS GOOD? BEQ DRTS ;*YES THEN EXIT DEC RCNT ;*NO. DONE WITH RETRYS? BPL CLD1 :* NO GO DO AGAIN JMP CIOER DRTS RTS ; ; DISK HANDLER FOR 128 OR 256 BYTE DISKS ; DKHND STY DSTATS ;*COMMAND FOR SIO LDY DCOMND ;*IS IT STATUS? CPY #$53 ;*YES SKIP BEQ DKHND1 ;*NO SET UP FOR READ OR WRITE LDA DLENLO ;* STA DCBCNT ;*STORE DISK BUFFER LDA DLENHI ;*LENGTH STA DCBCNT+1 ;* LDA DTYMO ;*NO SET TIMEOUT STA DCBTO ;* DKHND1 LDA #$31 ;*SET SERIAL BUS ID STA DCB ;* LDA UNNO ;*SET UNIT # STA DUNIT ;* JSR SIO ;*GO TO DISK ACCESS LDA DSTATS ;*STORE ERROR STATUS RTS ; ; ASCCON - CONVERT VALUE IN A TO 2 HEX DIGITS IN ASCII (X=HI,A=LO) ; ASCCON STA T1 LSR A LSR A LSR A LSR A JSR NIBCON CONVERT HI NIBBLE TAX LDA T1 AND #$F JSR NIBCON RTS ; ; NIBCON - CONVERT NIBBLE IN A TO ASCII HEX IN A ; NIBCON CMP #$A BPL ATOF CLC ADC #'0 RTS ATOF CLC ADC #'A-$A RTS ; ; ; ; S U B R O U T I N E S ; ; ; ; ; INITIO - CLOSE ANY OPEN IOCBS ; INITIO LDX #$10 IIO1 LDA ICHID,X CMP #$FF CHECK FOR CLOSED IOCB BEQ NXIOCB ALREADY CLOSED, CHECK NEXT IOCB LDA #CLOSE STA ICCOM,X JSR CIO NXIOCB TXA CLC ADC #$10 TAX CPX #$80 IF PAST LAST IOC BNE IIO1 RTS ; ; GETLIN LDA #CR LDX #79 STA LINE,X DEX BPL *-4 LDA #0 STA PTR STA IPTR STA PER JSR CIOGET JSR SCROL RTS ; ; ; ; CIOGET - GET LINE OF INPUT FROM SCREEN EDITOR ; CIOGT1 LDA #GETRCD+TEXT STA ICCOM SCREEN EDIT IOCB LDA #LINEL STA ICBAL LDA #LINEH STA ICBAH LDA #80 STA ICBLL LDA #0 STA ICBLH LDX #0 JMP CIO READ RECORD FROM SCREEN EDITOR CIOGET JSR CIOGT1 ;CALL CIO CPY #$80 CHECK FOR BREAK ABORT STATUS BNE *+5 JMP MENUSL RTS ; ; ; CHRGET - GET 1 CHAR FROM EDITOR IN A. ; CHRGET LDX #$30 LDA #GETCHR+TEXT STA ICCOM,X LDA #LINEL STA ICBAL,X LDA #LINEH BUF ADR SHOULDNT MATTER BUT JUST IN CASE STA ICBAH,X LDA #0 STA ICBLL,X LDA #0 STA ICBLH,X JSR CIO RTS ; ; PERX - EXIT IF PARAMETER ERRORS ; PERX BIT PER BMI PERX1 RTS PERX1 JMP MENUSL ; ; ; ;GET FILESPEC FROM INPUT LINE GETFIL LDY PTR LDX IPTR LDA #15 STA CTR ;AVOID GETTING JUNK ON VERY SHORT PARAMS LDA LINE,X CMP #', BEQ ADDC CMP #CR BEQ ADDC LDA LINE+1,X CMP #', BEQ GT1 CMP #CR BEQ GT1 LDA #': LOOK FOR : IN FILESPEC CMP LINE+2,X SEE IF HAVE COMPLETE FILESPEC ALREADY BEQ CFTE CMP LINE+1,X BNE GT1 DEC CTR LDA LINE,X CMP #'A BPL CFTE HAVE X:FILE, COMPLETE FILESPEC ;IF FALLS THRU, IS UNIT:FILE; ADD D GT2 LDA #'D STA PAR,Y INY BPL CFTE GT1 DEC CTR CMP LINE,X AN UNLIKELY CASE (:FILE) BEQ GT2 TREAT :FILE AS U:FILE DEC CTR ADDC LDA #'D STA PAR,Y INY LDA #': STA PAR,Y INY CFTE LDA #0 STA OPT CFTE1 LDA LINE,X STA PAR,Y INX INY CMP #CR LOOK FOR TERMINATOR BEQ EOC CMP #', BEQ EOC CMP #'/ BEQ POPT DEC CTR BPL CFTE1 ;GETS HERE IF TOO MANY CHARS IN FILENAME LDA #NTLL LDX #NTLH JSR DSPLIN NAME TOO LONG DEC PER SET PARAMETER ERROR FLAG EOC STX IPTR STY PTR RTS POPT LDA LINE,X STA OPT INX LDA LINE,X STA PAR-1,Y CHANGE STORED TERMINATOR TO , OR CR I HOPE INX BPL EOC NTL .BYTE 'NAME TOO LONG',CR HILO NTL ; ; DSPMSG - DISPLAY N BYTES ; BUFFER POINTER AND LENGTH ARE ALREADY IN IOCB0 ; DSPMSG LDA #PUTCHR STA ICCOM LDX #0 JSR CIO1 RTS ; ; DSPLIN - DISPLAY ONE LINE OF TEXT ; A=LO,X=HI ADDRESS DSPLIN STA ICBAL ADDRESS OF LINE TO IOCB STX ICBAH LDA #PUTRCD+TEXT STA ICCOM LDA #0 SET BUFF LEN STA ICBLH LDA #80 STA ICBLL LDX #0 JSR CIO1 RTS ; ; CIO1 JSR CIO CPY #$80 BNE *+5 JMP MENUSL RETURN TO MENU SELECT IF BREAK RTS ; ; SCROL - DO SCROLLING OF AREA BELOW MENU ; SCROL LDA #0 TAX STA ICBLH,X LDA #10 STA ICBLL,X LDA #ZAPH STA ICBAH,X LDA #ZAPL STA ICBAL,X JSR DSPMSG RTS ZAP .BYTE CUP,CUP,CUP,CUP,CUP .BYTE DLL,CDN,CDN,CDN,CDN HILO ZAP ; ; PIOCB - POINT IOCB AT PAR(PTR) ; PIOCB LDA #PARL CLC ADC PTR STA ICBAL,X LDA #PARH ADC #0 STA ICBAH,X RTS ; CIOER CLC ROL A ERROR*2 TAY AND #$40 SEE IF FILE ERROR (AX) BEQ NFE IF NO TYA AND #$3F CLEAR THAT BIT TAY LDA FEP,Y GET FILE ERROR MESSAGE POINTER LDX FEP+1,Y JMP CIEX NFE LDA CEP,Y CIO ERROR MESSAGE POINTER LDX CEP+1,Y CIEX JSR DSPLIN JSR CLOSX CLOSE IOCBS 10,20 JMP MENUSL ; ; CLOSX - CLOSE IOCBS 10,20 ; CLOSX LDA #CLOSE STA ICCOM+$10 CLOSE IOCBS 10,20 STA ICCOM+$20 LDX #$10 JSR CIO LDX #$20 JSR CIO RTS ; ; ; ; ; GETNO - GET HEX NUMERIC PARAMETER FROM LINE(IPTR). ; RETURN A=LO, X=HI. PER SET MINUS IF ERROR. ; INC IPTR PAST PARAM. ; GETNO LDA #4 MAX NO DIGITS STA CTR LDA #0 STA T1 STA T1+1 INIT TEMP TO BUILD NUMBER IN GHB LDX IPTR LDA LINE,X GET CHAR INC IPTR CMP #CR SEE IF TRMINATOR BEQ GND CMP #', BEQ GND JSR HEXCON CONVERT ASCII TO NIBBLE BMI ERRX IF ERROR LDY #3 SHIFT T1,T1+1 BY 4 SHT1 CLC ROL T1+1 ROL T1 DEY BPL SHT1 ORA T1+1 OR IN NEW NIBBLE STA T1+1 DEC CTR COUNT DIGIT BPL GHB LOOP UNLESS TOO MANY DIGITS LDA #TMDL LDX #TMDH ERRX1 JSR DSPLIN DEC PER RTS GND LDA T1+1 LDX T1 RTS ERRX LDA #IHPL INVALID HEX PARAM LDX #IHPH BNE ERRX1 TMD .BYTE 'TOO MANY DIGITS',CR HILO TMD IHP .BYTE 'INVALID HEXADECIMAL PARAMETER',CR HILO IHP ; ; ; HEXCON - CONVERT ASCII CHAR IN A TO HEX NIBBLE IN A. RETURN ; MINUS CONDITION, A=FF IF ERROR. ; HEXCON SEC SBC #'0 BMI ERRX2 ASCII BELOW '0' CMP #10 BMI OKX 0-9 CONVERTED SO EXIT SEC SBC #'A-'0-10 CMP #10 CONVERTED VALUE MUST BE 10 OR MORE BMI ERRX2 BETWEEN '9' AND 'A' CMP #$10 BMI OKX A-F CONVERTED ERRX2 LDA #$FF OKX CMP #0 SET STATUS BY VALUE IN A RTS ; ; ; TSTEOF ; TSTEOF LDA DBUF+126 BNE TSTRT ;TEST FOR ZERO FORWARD POINTER LDA #$03 ;DETECT EOF WITH BEQ=TRUE IN CALLER AND DBUF+125 ; TSTRT RTS ; ; ; SETEOF ; SETEOF LDA #$FC AND DBUF+125 ;SET FORWARD POINTER TO ZERO STA DBUF+125 ; TO INDIC^ATE EOF LDA #0 STA DBUF+126 RTS CEP .WORD BKA,DNR,NED,DER,IVC,DNO,IIN,WPD,EOF,CFE,E8A,E8B,E8C,DCE .WORD E8E,E8F,E90,RWC FEP .WORD DNE,NSB,NSA,FIO,FNM,FNE,PDL,FLO,DCI,DRF,FNF,PIN,EAC,EAD BKA .BYTE 'BREAK KEY ABORT',CR DNR .BYTE 'IOCB ALREADY OPEN',CR NED .BYTE 'NON EXISTENT DEVICE',CR DER .BYTE 'IOCB WRITE ONLY ERROR',CR IVC .BYTE 'ILLEGAL HANDLER COMMAND',CR DNO .BYTE 'DEVICE/FILE NOT OPEN',CR IIN .BYTE 'INVALID IOCB NUMBER',CR WPD .BYTE 'IOCB WRITE ONLY ERROR',CR EOF .BYTE 'END OF FILE',CR CFE .BYTE 'RECORD TRUNCATION',CR E8A .BYTE 'DEVICE TIMEOUT',CR E8B .BYTE 'DEVICE NAK',CR E8C .BYTE 'SERIAL FRAME ERROR',CR DCE .BYTE 'CURSOR OUT OF RANGE',CR E8E .BYTE 'SERIAL BUS ERROR',CR E8F .BYTE 'CHECKSUM ERROR',CR E90 .BYTE 'DEVICE DONE ERROR',CR RWC .BYTE 'ILLEGAL SCREEN MODE',CR EAC .BYTE 'FUNCTION NOT IMPLEMENTED',CR EAD .BYTE 'NOT ENOUGH RAM FOR GRAPHICS MODE',CR DNE .BYTE 'DRIVE NUMBER ERROR',CR NSB .BYTE 'TOO MANY OPEN FILES',CR NSA .BYTE 'DISK FULL',CR FIO .BYTE 'FATAL FMS I/O ERROR',CR FNM .BYTE 'FILE NUMBER MISMATCH',CR FNE .BYTE 'FILENAME ERROR',CR PDL .BYTE 'POINT SECTOR LENGTH',CR FLO .BYTE 'FILE LOCKED',CR DCI .BYTE 'DEVICE COMMAND INVALID',CR DRF .BYTE 'DIRECTORY FULL',CR FNF .BYTE 'FILE NOT FOUND',CR PIN .BYTE 'POINT COMMAND INVALID',CR TSTEND LDA DLENHI ;*TEST FOR 128 OR 256 BYTE DEVICE BEQ T128 ;*128 LDA TYPSEC ;*256.S IT 1ST 128 OR SECOND BEQ T128 ;1ST. TEST FOR INDEX >80 CMP #$F9 ;*SECOND 128 BYTES OF SECTOR. IS INDEX TO HIGH? BCS TOUT ;*YES, EXIT CPY #$80 ;* NO. IS IT TO LOW? BCS TCLC ;* NO. EXIT WITH CLC SEC ;*SEC MEANS DBUF INDEX IS OUT OF RANGE BCS TOUT ;*EXIT WITH SEC T128 CPY #$81 ;*IS INDEX<81 TOUT RTS ;*EXIT.SEC MEANS DNUF INDEX IS OUT OF RANGE ;* CLC ' ' ' IN RANGE TCLC CLC ;*INDEX IN RANGE RTS ;SAME EXIT AS ABOVE DUPN =* END OF DUP HILO DUPN .END E; THIS PROGRAM WRITES A SINGLE FILE TO THE CASSETTE AND IS ; USED IN CONJUNCTION WITH A PROCEDURE TO MAKE CASSETTE ; BOOTABLE FILES. THE FOLLOWING TWO SYMBOLS MUST BE EQUATED ; USING THE MEMORY LIMITS OF THE PROGRAM TO BE COPIED. ; ; 'PST' = PROGRAM START ADDRESS (SEE SAMPLE PROGRAM) ; 'PND' = PROGRAM END ADDRESS (SEE SAMPLE PROGRAM) ; PST= $0700 PND= $08A0 FLEN= PND-PST+127/128*128 ; ROUND UP TO MULTIPLE OF 128. CR = $9B OPEN = $03 ICCOM = $342 OPNOT = $08 ICAX1 = $34A ICAX2 = $34B ICBAL = $344 ICBAH = $345 CIOV = $E456 PUTCHR = $0B ICBLL = $348 ICBLH = $349 CLOSE = $0C *= $B000 ; THIS PROGRAM'S ORIGIN. BOOTB LDX #$10 ; USE IOCB #1. ; FIRST OPEN THE CASSETTE FILE FOR WRITING. LDA #OPEN ; SETUP FOR DEVICE "OPEN". STA ICCOM,X LDA #OPNOT ; DIRECTION IS "OUTPUT".  STA ICAX1,X LDA #$80 ; SELECT SHORT IRG. STA ICAX2,X LDA #.LOW.CFILE ; SETUP POINTER TO DEVICE NAME. STA ICBAL,X LDA #CFILE/256 STA ICBAH,X JSR CIOV ; ATTEMPT TO OPEN FILE. BMI CERR ; NOW WRITE THE ENTIRE FILE AS ONE OPERATION. LDA #PUTCHR ; SETUP FOR "PUT CHARACTERS". STA ICCOM,X LDA #.LOW.PST ; POINT TO START OF APPLIC. PROG. STA ICBAL,X LDA #PST/256 STA ICBAH,X LDA #.LOW.FLEN ; SETUP # OF BYTES TO WRITE. STA ICBLL,X LDA #FLEN/256 STA ICBLH,X JSR CIOV ; WRITE ENTIRE FILE. BMI CERR ; ERROR. ; NOW CLOSE THE FILE AFTER SUCCESSFUL WRITE. LDA #CLOSE ; SETUP FOR "CLOSE". STA ICCOM,X JSR CIOV ; CLOSE THE FILE. BMI CERR BRK ; STOP WHEN DONE. CERR BRK ; STOP ON ERROR. CFILE .BYTE 'C:',CR ; FILE NAME. ; THIS IS THE CARTRIDGE HEADER *= $BFF9 ; "A" CARTRIDGE. INIT RTS .WORD BOOTB .BYTE 0,5 .WORD INIT .END C; THIS PROGRAM FORMATS A DISKETTE ON D1: AND THEN WRITES ; CORVUS BOOT SECTORS. ; ; ; 'PST' = PROGRAM START ADDRESS ; 'PND' = PROGRAM END ADDRESS ; ; SECSIZ = 128 DSKTIM = $246 PST = $700 PND = $8FD  ; FLEN = PND-PST+127/128 # OF SECTORS TO IN BOOT ; DUNIT = $301 DCOMND = $302 DBUFLO = $304 DBUFHI = $305 DAUX1 = $30A DAUX2 = $30B ; DSKINV = $E453 ; ; *= $B000 COUNT *=*+1  ; ; BOOTB BRK ; LDA #1 STA DUNIT ; LDA #'! STA DCOMND GIVE D1: FORMAT COMMAND ; LDA #.LOW.BUFFER STA DBUFLO LDA #BUFFER/256 STA DBUFHI SET UP FAK E BUFFER FOR BAD SECTOR INFO ; LDA #$FF STA DSKTIM ALLOW LONG TIME FOR FORMAT ; JSR DSKINV HAVE O.S. DISK HANDLER FORMAT D1: ; ; ; LDA #.LOW.FLEN # OF SECTORS TO WRITE STA  COUNT ; LDA #1 STA DUNIT WRITE BOOT TO D1: ; LDA #'W STA DCOMND GIVE D1: WRITE COMMAND ; LDA #.LOW.PST POINT TO START OF BOOT STA DBUFLO LDA #PST/256 STA DBUFHI ; LDA #1 START BOOT ON D1: AT SECTOR 1 STA DAUX1 LDA #0 STA DAUX2 ; ; NOW WRITE ONE SECTOR AT A TIME ; BOT010 JSR DSKINV WRITE ONE SECTOR BMI DERR  BRANCH IF ERROR ; LDA DBUFLO INCREMENT BUFFER ADDRESS CLC ADC #SECSIZ STA DBUFLO LDA DBUFHI ADC #0 STA DBUFHI ; INC DAUX1 BNE BOT020  INC DAUX2 ; BOT020 DEC COUNT BNE BOT010 ; BRK ; ; DERR BRK ; ; BUFFER =*+256 ; *=$BFF9 INIT RTS .WORD BOOTB .BYTE 0,4 .WORD INIT ; .END LIST X ; .TITLE 'DUP FOR DUAL DENSITY VER 2D.1 11/18/80'^ H .TITLE 'CORVUS DUP VER A2D.1 APRIL 25,1981'^ H ; ; ;CHANGED FOR SYSTEM RESET -- DUPFLG ;ADDED INTERRUPT ROUTINES FROM SIO -- KB ;MIKE L. MODIFIED FOR TO LEAVE ROOM FOR CORVUS & ASSOCIATED PATCHES ;ADDED SAVE/RESTORE OF DOSINI VECTOR -- KB ; ; FILENAME = MIKEL.CDUPSRC ON TANDEM ; .PAGE ; **** EQUATES ****^ H ; ; ; CVECT1 = $1501 CORVUS VECTOR 1 - USER DISK HANDLER CVECT2 = CVECT1+3 CORVUS VECTOR 2 - CORVUS SIO ROUTINE CIO = $E456 ;DKHND = $E453 DKHND = CVECT1 ****** CORVUS ***** SETVBV = $E45C SYSVBV = $E45F XITVBV = $E462 CIOINV = $E46E MEMTOP =  $2E5 IRQEN = $D20E BRKKEY = $11 POKMSK = $10 DOSVEC = $A DOSINI = $C ;DOS INIT VECTOR WARMST = 8 LMARGN = $52 RMARGN = $53 CARTST = $BFFA INTRVEC = $20A ;INTERRUPT VECTOR LOC FOR SIO PATCH MEMLO = $2E7 SHFLOK = $2BE INITAD = $2E2 RUNAD = $2E0 ICHIDZ = $20 ICDNOZ = $21 ICBALZ = $24 ICBAHZ = $25 ICIDNO = $2E MAXDEV = $21 HATABS = $31A ;USRDOS = $1700 USRDOS = $1700+$400 FMS = $700 FMINIT = FMS+$E0 ;DOS = FMS+$E40 DOS = FMS+$E40+$400 WRMSTR = $E474 ;WARM START ENTRY VECTOR BSIOR = $772 ;ENTRY POINT TO FMS DISK HANDLER USED BY DUP DISK CDTMV3 = $21C ;ADDRESS OF SYSTEM TIMER # 3 CDTMF3 = $22A ;ADDRESS OF TIMER # 3 DONE FLAG ; CR = $9B CUP = $1C CDN = $1D CLF = $1E CRT = $1F DLL =  $9C CLSCR = $7D EOF = $88 ;ENDFILE RETURN CODE FROM CIO ; ; OPEN = $03 CLOSE = $0C PUTCHR = $0B GETCHR = $07 GETREC = $05 PUTREC = $09 RENAME = $20 DELETE = $21 FORMAT = $FE LOCK = $23 UNLOCK = $24 STAREQ = $53 ;STATUS COMMAND TO DISK CONTROLER ; IOCB1 = $10 ; DVSTAT = $2EA ;ADDRESS OF STATUS INFO STORED BY OS ; ; DCB = $300 DUNIT = DCB+1 DCOMND = DCB+2 DSTATS = DCB+3 DBUFLO = DCB+4 DBUFHI = DCB+5 DSLO = DCB+$A DSHI = DCB+$B ; IOCB = $340 ICHID = IOCB+0 ICDNO = IOCB+1 ICCOM = IOCB+2 ICSTA = IOCB+3 ICBAL  = IOCB+4 ICBAH = IOCB+5 ICBLL = IOCB+8 ICBLH = IOCB+9 ICAX1 = IOCB+10 ICAX2 = IOCB+11 ; SYSED = $0 OWRIT = $08 ORDWRT = $0C ; HILO .MACRO P1 P1&H = .HIGH.P1 P1&L =  .LOW.P1 .ENDM .PAGE ; **** ZERO PAGE VARIABLES ****^ H ; ; *=$18 JMPTBL *=*+2 RAMLO *=*+2 BUFADR = RAMLO ;SAVE AREA FOR BUFFER ADDRESS USED BY USEPGM .PAGE ; **** INIT CODE FOR DUP ****^ H ; ; ;  INITIALIZATION CODE FOR DUP - CALLS FMS INIT CODE. ; CALLED ON WARM START AND COLD START. ; *=DOS LDA #0 STA OPT LDA #MNDUPL STA DOSVEC LDA #MNDUPH STA DOSVEC+1  LDA #.LOW.ISRSIR ;SET UP INTERRUPT VECTORS FOR SIO PATCH. STA INTRVEC ;INSTEAD OF USING THE SERIAL INPUT READY LDA #.HIGH.ISRSIR ;SERVICE ROUTINE AND THE SERIAL OUTPUT STA INTRVEC+1 ;INTERRUPT SERVICE ROUTINE IN THE OS ROM LDA #.LOW.ISRODN ;USE THE VERSIONS IN RAM FOLLOWING THE STA INTRVEC+2 ;RESIDENT PORTION OF DUP. LDA #.HIGH.ISRODN STA INTRVEC+3 JSR FMINIT LDA WARMST  ;ON COLDSTART, LOAD AUTORUN.SYS BNE CKMDOS ;WARMSTART CHECK IF DUP WAS RUNNING LDA #AFL STA ICBAL+$10 LDA #AFH STA ICBAH+$10 JSR INITX ;CLEAR DUPFLG SHOW DUP NOT IN MEM!ORY. LDA #$C0 JSR STLOAD ;LOAD, INIT AND RUN THE AUTORUN FILE JMP CLOSX ;MAKE SURE IOCB #1 IS CLOSED & RETURN ; CKMDOS LDA DUPFLG ;SEE IF DUP WAS IN MEMORY BEQ INITX ;=ZERO THEN WASN"'T ; LDA MEMFLG ;SEE IF USER AREA WRITTEN TO MEM.SAV BEQ CLDSET ;=ZERO THEN WASN'T JSR LDMEM1 ;ELSE GET USER MEMORY BACK IN ; JSR RELDIN ;RESTORE THE DOSINI VECTOR FROM SAVE LOC JSR# INITX ;CLEAR DUPFLG JMP WRMSTR ;REDO WARMSTART ; INITX LDA #0 ;SAY DUP NOT IN MEMORY STA DUPFLG ;CLEAR FLAG RTS ; CLDSET STA WARMST ;NO VALID USER MEMORY BEQ INITX $ ;SET TO COLD START .PAGE ; **** LOADER ROUTINE ****^ H ; ; ; LOADS FROM THE FILE (MUST BE LOAD FORMAT) ; INTO MEMORY. RETURNS: ; X=0 LOAD OK ; X=1 OPEN ERRORS Y=CIO CODE ; X=2 READ ERRORS Y=CIO CODE ; % X=3 BAD LOAD FILE ; ON ENTRY, IOCB 1 POINTS TO FILENAME. ; DUPFLG .BYTE 0 ;FLAG -IF DUP IN MEMORY NOT ZERO OPT .BYTE 0 ;HOLDS VALUE OF OPTION GIVEN BY USER LOADFG .BYTE 0 ;FLAG = $80 IF MEMORY FILE DOESN'T HAVE TO& BE LOADED HDBUF *=*+4 HILO HDBUF SFLOAD LDA #$80 STLOAD STA LOADFG LOAD LDA #.LOW.RTS STA RUNAD LDA #.HIGH.RTS STA RUNAD+1 ;MAKE RUN AT EOF DEFAULT TO RTS LDX #$10 ' LDA #OPEN STA ICCOM,X LDA #4 ;OPEN TYPE=INPUT STA ICAX1,X JSR CIO ;TRY TO OPEN FILE BPL RDLF ;CONT IF OK LDA #1 ;OPEN ERRORS BNE CLFX ( ;CLOSE AND EXIT RDLF LDX #$10 LDA #DBUFL STA ICBAL,X LDA #DBUFH STA ICBAH,X LDA #2 STA ICBLL,X LDA #0 STA ICBLH,X STA MEMLDD ;CL)EAR MEM.SAV LOADED FLAG LDA #GETCHR STA ICCOM,X JSR CIO BMI ERST ;IF ERRS LDA #$FF CMP DBUF ;CHECK FOR VALID LOAD FILE BNE LNLF CMP DBUF+1 * BNE LNLF ;BRANCH IF NOT A LOAD FILE RDDRC LDX #$10 LDA #HDBUFL STA ICBAL,X LDA #HDBUFH STA ICBAH,X LDA #4 RDDRC1 STA ICBLL,X LDA #0 STA ICBLH,X + JSR CIO ;NO ERROR CHECK SO CAN CATCH EOF BPL STOK ;IF NO ERROR CPY #$88 ;SEE IF EOF BNE ERST ;IF SOME ERROR STATUS ; ;EOF SO DONE, EXIT ; JSR CLOSX ;CLOSE IOCB'S 1 A,ND 2 BIT OPT BMI DRUN ;BRANCH IF NO RUN OPTION JSR JMPRUN ;JUMP THROUGH RUN VECTOR DRUN LDA #0 ;OK STATUS BIT LOADFG ;WAS MEMORY SWAPPED? STA LOADFG BMI - CLFX ;BRANCH IF MEMORY WASN'T SWAPPED JSR MEMSVQ ;DOES MEMORY SAVE FILE EXIST? BMI DRUN1 ;BRANCH IF NOT PLA PLA JMP GOOD ;WRITE MEMORY AND RELOAD DUP ; ; SEE IF DUP WRITTEN OVER. .IF IS RELOAD & TELL USER NEED MEM.SAV TO ; LOAD THIS FILE. ; DRUN1 LDA DUPFLG ;SEE IF DUP CLOBBERED BNE DRUN2 ;NO, THEN RETURN LDA #NMSFL ;ELSE TELL USER NEED MEM.SAV LDX #NMSFH JSR PRNT/MSG ;PRINT MSG JMP RRDUP ;RELOAD & RUN DUP ; ; RETURN TO CALLING ROUTINE ; DRUN2 LDA #0 ;NO DUP ERR MSG ON EOF CLFX TAX RTS RTS ; ; ERROR RETURNS ; LNLF JSR CLOSX LDA #3 ;BA0D LOAD FILE BNE CLFX ERST TYA PHA JSR CLOSX PLA TAY BNE CLFX ; ; CONTINUE WITH LOAD - CHECK LOAD ADDRESS FOR HEADER ; HEADER IF HAVE CONCATENATED LOAD FILES ; STOK LDX #$10 LD1A HDBUF ;MOVE PARAMS TO IOCB STA ICBAL,X PHA LDA HDBUF+1 STA ICBAH,X TAY PLA INY ;WAS ADDRESS FF? BNE ADOK ;BRANCH IF NOT TAY I2NY ;OTHER BYTE FF? BNE ADOK ;BRANCH IF NOT ; ; HAVE A HEADER & START ADDRESS - GET END ADDRESS FOR TEXT & DO AGAIN ; LDA HDBUF+2 STA HDBUF LDA HDBUF+3 STA HDBUF+1 ;MOVE 3LOAD ADDRESS LDA #.LOW.HDBUF+2 STA ICBAL,X LDA #.HIGH.(HDBUF+2) STA ICBAH,X ;SO LOAD ADDRESS DOESN'T GET WIPED OUT BY END ADDRESS LDA #2 JMP RDDRC1 ; ; GET LENGTH OF TEXT. THEN D4ETERMINE IF IN DUP ; ADOK LDA HDBUF+2 SEC SBC HDBUF STA ICBLL,X LDA HDBUF+3 SBC HDBUF+1 STA ICBLH,X LDA HDBUF+1 JSR AWDQ ;IS BEGINNING ADDRESS WITHI5N DUP? BCS AWD ;BRANCH IF SO LDA HDBUF+3 JSR AWDQ ;IS ENDING ADDRESS WITHIN DUP? BCS AWD ;BRANCH IF SO ; ; SINCE TEXT IN DUP, LOAD MEM.SAV IF NECCESARY ; ANWD LDA MEMLDD 6BMI AWD ;BRANCH IF MEM.SAV ALREADY LOADED LDA #$80 ORA LOADFG STA LOADFG ;SET MEM.SAV DOESN'T HAVE TO BE LOADED FLAG AWD INC ICBLL,X BNE *+5 INC ICBLH,X BIT L7OADFG ;DOES MEMORY HAVE TO BE LOADED BMI DLM ;BRANCH IF NOT LDA MEMLDD ;WAS MEM.SAV ALREADY LOADED? BMI DLM ;BRANCH IF SO DEC MEMLDD JSR LDMEM ;LOAD MEM.SAVE FILE (IF8 IT EXISTS) LDA #0 ;SHOW USER AREA NOT DUP IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOSINI VECTOR ; ; SET NO INIT ADDR DEFAULT THEN READ IN TEXT & ATTEMPT INIT ; DLM LDX #$10 LDA #.LOW.9RTS STA INITAD LDA #.HIGH.RTS STA INITAD+1 ;INIT DEFAULTS TO AN RTS JSR CIO ;READ DATA DIRECTLY TO MEMORY BPL DLM1 JMP ERST ;IF ERRORS DLM1 BIT OPT BMI: DINIT ;BRANCH IF NOGO OPTION JSR JMPINT ;DO INIT DINIT JMP RDDRC ;GET NEXT SECTION OF LOAD FILE ; ; SUBROUTINE TO DETERMINE IF ADDRESS IS WITHIN DUP ADDRESS SPACE. ; ENTRY - HI BYTE OF ADDRESS IN ;REG. A ; RETURNS - CARRY SET : WITHIN DUP ; CARRY CLR : NOT WITHIN DUP ; AWDQ CMP #NDOSH BCC AWDQR ;BRANCH IF HI BYTE LT DUP START CMP #NMDUPH+1 ROL A EOR <#1 LSR A ;COMPLEMENT CARRY AWDQR RTS ; ; JMPINT JMP (INITAD) JMPRUN JMP (RUNAD) ; ; MEMLDD .BYTE 0 AF .BYTE 'D1:AUTORUN.SYS',CR HILO AF NMSF .BYTE 'NEED MEM.SAV TO LOAD THIS FILE.',CR HI=LO NMSF .PAGE ; **** CREATE MEM.SAV FILE ****^ H ; ; ;ROUTINE WRITTEN BY MICHAEL EKBERG,APRIL 21,1980 ;THIS ROUTINE CREATES A FILE ON DISK OF DATA FROM MEMORY ;CREATE FILE CALLED 'D1:MEM.SAV',SET Y=1 ; ;THE RAM TO BE OCCUPIED BY DUP IS S>TORED BY THIS ROUTINE INTO 'MEMORY.SAV' ; ; NAME .BYTE 'D1:MEM.SAV',CR HILO NAME MWRITE JSR CLOSX ;CLOSE IOCB AND OPEN IT TO WRITE LDA #OWRIT ; STA ICAX1,X ; JSR OREST ;OPEN FOR W?RITE BMI ERRWR ;IF ERROR THEN JMP AND RET ; ; ;WRITE MEMORY BLOCK ; LDA #PUTCHR STA ICCOM,X LDA #NDOSL ;STORE START OF BLOCK FOR CIO STA ICBAL,X LDA #NDOSH ;START ADDR @(HIGH) STA ICBAH,X LDA #MLENL+1 ;LENGTH OF BLOCK STA ICBLL,X LDA #MLENH ;LENGTH(HIGH) STA ICBLH,X JSR CIO ;WRITE DATA BLOCK BMI ERRWR ;IF WRITE ERROR TAHEN JMP JSR CLOSX BMI ERRWR LDY #0 RET RTS ; OREST LDA #OPEN STA ICCOM,X LDA #NAMEL ;ROUTINE TO COMPLETE OPEN OF 'D1:MEMORY.SAV STA ICBAL,X ;CALLING SUB SUPPLIES 'RBEAD' OR 'WRITE' LDA #NAMEH ;IN ICAX1 STA ICBAH,X JMP CIO ; ERRWR STY TEMP+1 ;TEMP STORE FOR Y FLAG JSR CLOSX ;CLOSE #$20 LDA #DELETE ;DELETE PART OF MENSAV STA C ICCOM,X JSR OREST TEMP LDY #0 ;RESTORE FLAG RTS RETURN TO MAIN CALLER .PAGE ; **** ENTRY POINT ON 'DOS' CALL ****^ H ; ; INISAV .DBYTE 0 ;DOSINI VECTOR SAVE AREA MEMFLG .DBYTE 0 MNDUP LDX #0 STX MEMFLG STX LOADFG DEX STX WARMST JSR INITIO JSR MEMSVQ ;FIND OUT IF FILE D1:MEM.SAV EXISTS BPL GOOD ;BRANCH IF MEM.SAV FILE EXITS E LDA #0 STA WARMST ;CLEAR WARM START FLAG BEQ FINAL ; ; GOOD JSR MWRITE ;WRITE USER AREA TO MEM.SAV BMI ERROR DEC MEMFLG ;SHOW MEMORY WRITTEN BMI FINAL ; ERROR LDFA #.LOW.ERRMES ;PRINT ERROR OCCURED MSG LDX #.HIGH.ERRMES JSR PRNTMSG ;GOTO MSG PRINTER ; LDA #.LOW.ERR ;PRINT QUERY TO RUN DOS LDX #.HIGH.ERR JSR PRNTMSG ;GOTO MSG PRINTER ; ; WAGIT FOR Y TO RUN DOS ; LDA #GETREC STA ICCOM LDA #STAKL STA ICBAL LDA #STAKH STA ICBAH LDA #2 STA ICBLL LDA #0 STA ICBLH JSR H CIO LDA STAK ;SEE IF Y TYPED CMP #'Y BNE RTCART ;BRANCH IF NOT LDA #0 STA WARMST ; FINAL LDX #$20 LDA #CLOSE STA ICCOM,X ;SET UP CLOSE COMMAND I JSR CIO ;PERFORM CLOSE COMMAND ; RRDUP LDA DOSINI ;SAVE DOSINI VECTOR STA INISAV LDA DOSINI+1 STA INISAV+1 ; LDA #.LOW.DOS ;SET UP DUP INIT ADDRESS AS DOSINI VECTOR STA J DOSINI LDA #.HIGH.DOS STA DOSINI+1 ; RRDUP1 LDA #.LOW.DUPSYS LDX #$10 STA ICBAL,X LDA #.HIGH.DUPSYS STA ICBAH,X LDY #0 STY OPT ;ASSURE NO /N OPKTION IN EFFECT DEY ;SHOW THAT DUP IS IN MEMORY STY DUPFLG JSR SFLOAD ;LOAD DUP.SYS AND RUN IT RTCART RTS EC .BYTE 'E:',CR HILO EC HILO MNDUP DUPSYS .BYTE 'D1:DUP.SYS',CRL ; ERRMES .BYTE 'ERROR-SAVING USER MEMORY ON DISK',CR ERR .BYTE 'TYPE Y TO STILL RUN DOS',CR .PAGE ; **** SUBROUTINES FOR RESIDENT DUP ****^ H ; ; ; ROUTINE TESTS IF MEM.SAV IS PRESENT ON THE DISK. ; RETURNS - MINUS IFM NOT THERE ; PLUS IF MEM.SAV IS THERE ; MEMSVQ JSR CLOS20 ;CLOSE IOCB # 2 LDA #OPEN STA ICCOM,X LDA #NAMEL STA ICBAL,X LDA #NAMEH STA ICBAH,X LDA N #ORDWRT STA ICAX1,X ;TRY TO OPEN D1:MEM.SAV FOR READ/WRITE JSR CIO PHP ;SAVE STATUS JSR CLOS20 ;CLOSE MEM.SAV PLP ;RESTORE STATUS RTS ; ; ; SAVE FOILE SUBROUTINE - WRITE FILE BODY, INIT, & RUN VECTORS ; WDR1 LDA #0 ;THIS IMMEDIATE VALUE MODIFIED BEQ WDR2 ;BRANCH IF MEMORY FILE DOESN'T HAVE TO BE LOADED JSR LDMEM WDR2 LDX #$10 JSR CIO P ;DO SAVE - WRITE BODY TO DISK INITQ LDA #0 ;THIS IMMEDIATE VALUE CHANGED DURING SAVE BEQ RUNQ ;SET TO FF WHEN AN INIT VECTOR IS PRESENT INC INITQ+1 LDA INITAD STA VECTR ;IF QINIT VECTOR FOR FILE SAVE IT LDA INITAD+1 STA VECTR+1 LDA #.LOW.INITAD TAX STA LDST LDA #.HIGH.INITAD JSR WRVEC RUNQ LDA #0 ;THIS IMMEDIATE VALUE MODIFIED R BEQ NORNAD ;SET TO FF WHEN A RUN VECTOR IS PRESENT INC RUNQ+1 LDA RUNAD STA VECTR ;IF RUN VECTOR FOR FILE SAVE IT LDA RUNAD+1 STA VECTR+1 LDA #.LOW.RUNAD TSAX STA LDST LDA #.HIGH.RUNAD JSR WRVEC NORNAD JSR CLOSX ;CLOSE IOCBS 1 &2 LDA MEMFLG AND WDR1+1 BEQ DRRDUP INC WDR1+1 ;RESET MEM.NEEDS TO BE LOADED FLAG T JMP RRDUP1 ;RELOAD & RUN DUP DRRDUP JMP DOSOS ;RUN THE SWAPPED IN DUP ; ; ; WRVEC STA LDST+1 INX STX LDND STA LDND+1 LDX #$10 LDA #.LOW.LDST STA ICBAL,X U LDA #.HIGH.LDST STA ICBAH,X LDA #6 STA ICBLL,X LDA #0 STA ICBLH,X JMP CIO ;WRITE INIT OR RUN ADDRESS ; ; ; JUMP TO CARTRIDGE ; CLMJMP JSR LDMEM LDA V #0 ;SHOW DUP NO LONGER IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOSINI VECTOR JMP (CARTST) ;JUMP TO CARTRIDGE ; ; ; LOAD MEM.SAV (IF IT EXISTS) BEFORE RUN AT ADDRESS ; LMTR JSR LDMEM ;LOAD MWEM.SAVE IF IT EXISTS LDA #0 ;SHOW THAT DUP NO LONGER IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOSINI VECTOR JMP (RAMLO) ;RUN AT ADDRESS ; ; RESTORE DOSINI VECTOR FROM SAVE AREA ; RELDIN LDAX INISAV STA DOSINI LDA INISAV+1 STA DOSINI+1 RTS ; ; ; SUBROUTINE - LDMEM ; LOAD MEM.SAV IF IT EXISTS ; LDMEM LDA MEMFLG BNE LDMEM1 ;BRANCH IF MEMORY WAS SAVED RTSY LDMEM1 JSR MEMSVQ BPL LDMEM2 ;BRANCH IF MEM.SAV FILE DOES EXIST LDA #0 ;TELL CART PGM AREA CLOBBERED STA WARMST BEQ CLOS2 ;GO CLOSE AND GOTO CART ; LDMEM2 LDA #OPEN STA Z ICCOM,X JSR CIO ;REOPEN MEM.SAV LDA #GETCHR STA ICCOM,X LDA #MLENL+1 STA ICBLL,X LDA #MLENH STA ICBLH,X LDA #NDOSL STA ICBAL,X [ LDA #NDOSH STA ICBAH,X JSR CIO CLOS2 LDA #CLOSE STA ICCOM,X JMP CIO ;CLOSE MEM.SAV ; ; CLOSE ALL IOCBS & RE-OPEN ZERO AS SCREEN EDITOR ; INITIO JSR CIOINV ;THIS ROUTINE CLOSES AL\L IOCB'S ; THEN REOPENS THE SCREEN EDITOR LDX #0 LDA #OPEN STA ICCOM,X LDA #ECL STA ICBAL,X LDA #ECH STA ICBAH,X LDA #ORDWRT STA ICAX1,X ]JSR CIO ; LDX #0 ;SET TIMER TO DELAY UNTIL STX CDTMV3 ;SCREEN COMES BACK ON - DMA RESTORED STX CDTMV3+1 ;1ST CLEAR TIMER LDY #1 ;WAIT FOR ONE VBLANK LDA #3 ;US^E TIMER #3 STA CDTMF3 ;SET TIME OUT FLAG NON-ZERO JSR SETVBV ;SET VBLANK TIMERS WAITIM LDA CDTMF3 ;WHEN FLAG BECOMES ZERO THEN TIME OUT BNE WAITIM ; RTS ; ; CLOSX - CLOSE IOCBS 10,20 ; CLOSX _ LDA #CLOSE LDX #$10 STA ICCOM,X JSR CIO ; ; ENTRY TO CLOSE IOCB # 2 ONLY ; CLOS20 LDX #$20 LDA #CLOSE STA ICCOM,X JMP CIO ; ; SUBROUTINE - PRNTMSG ; PUTS A CHARACTE`R STRING TERMINATED BY A CARRIAGE RETURN CHAR TO ; SCREEN EDITOR. ; ; ENTRY - REG A : LOW BYTE MSG ADDRESS ; REG X : HI BYTE MSG ADDRESS ; ; PUT PARAMS IN IOCB - USE IOCB 0 FOR SCREEN EDITOR ; PRNTMSG STA ICBAL a ;SET MSG ADDR IN IOCB BUFF ADDR STX ICBAH ; ; SET UP REST OF IOCB ; LDA #$80 ;SET IN BUFFER LENGTH STA ICBLL ;ASSUME 128 BYTES MAX LDX #0 ;USE REG X TO SET IN IOCB INDEX FOR CIO b STX ICBLH LDA #PUTREC ;PUT MSG STA ICCOM ; ; TEST IF DUP IS RESIDENT - IF IS THEN USE INDIRECT CIO ROUTINE TO TEST ; FOR BREAK KEY ABORT ; LDA DUPFLG ;=ZERO IF NON-RESIDENT DUP NOT IN MEMORY BNE c INMEM ;IN MEMORY THEN USE INDIRECT CIO CALL ; JMP CIO ;ELSE GO DIRECT TO CIO & RETURN ; INMEM JMP CIO1 ;USE CIO CALL WITH TEST FOR BREAK KEY ABORT ; ; SAVH .BYTE $FF,$FF HILO SAVH LDST *=*+2 d HILO LDST LDND *=*+2 VECTR *=*+2 BUFL = VECTR ;USED BY DUP DISK-STORES SECT SIZE FOR CURRENT MOVE .PAGE ; **** SIO INTERRUPT SERVICE ROUTINES ****^ H ; ; ; EQUATES FOR INTERRUPT ROUTINES MOVED FROM SIO ; ; e ZERO PAGE ; BUFRLO = $32 ;POINTER TO BYTE TO SEND OR RECEIVE BUFRHI = $33 BFENLO = $34 ;POINTER TO BYTE AFTER END OF BUFFER BFENHI = $35 CHKSUM = $31 ;LOC TO STORE DATA FRAME CHECKSUM CHKSNT f = $3B ;CHECKSUM SENT FLAG- =FF SENT NOCKSM = $3C ;FLAG NO CHECK SUM TO BE RECEIVED-NOT ZERO STATUS = $30 ;HOLD FOR STATUS TO BE PUT IN DCB BUFRFL = $38 ;FLAG-IF FF RECEIVE BUFFER IS FULL RECVDN = q fDOS SYSfDUP SYSf 1CBOOTSRC f:CFIXSRC f CORCASBW f CORDISBW f}CORDUPA fiCORFMSA fDUP20S f{DUPDUAL fgFMSDUAL $39 ;FLAG RECEIVE NOT DONE. USED BY WAIT LOOP ; ; HARDWARE REGISTERS USED IN SIO INTERRUPT ROUTINES ; SKRES = $D20A ;SERIAL PORT STATUS RESET ON POKEY SEROUT = $D20D ;SERIAL OUTPUT REGISTER SERIN = SERrOUT ;SERIAL PORT INPUT REG ON POKEY SKSTAT = $D20F ;SERIAL PORT STATUS REG ON POKEY ; ; ERROR CODES RETURNED BY SIO ; FRMERR = $8C ;FRAMING ERROR ON INPUT OVRRUN = $8E ;DATA FRAME OVER RUN-BIT D5 IN SKSTAT CHKsERR = $8F ;DATA FRAME CHECKSUM ERROR .PAGE ; **** INTERRUPT SERVICE ROUTINE TO OUTPUT DATA NEEDED ****^ H ; ; ; ; IT UPDATES THE BYTE TO PUT ON SERIAL I/O BUS POINTER ; UNTIL END OF BUFFER. AFTER EACH UPDATE OtF THE PTR ADDS THE ; VALUE OF THE BYTE TO THE CHECKSUM. OUTPUTS THE CHECKSUM WHEN ; PTR EQUALS THE END OF BUFFER PTR (POINTS TO BYTE AFTER BUFFER). ; RETURNS TO THIS ROUTINE AFTER CHECKSUM PASSED AND RESETS POKEY ; INTERRUPT REGu TO HAVE THE TRANSMIT DONE ROUTINE CALLED TO END ; WAIT LOOP (SEE SIO LISTING). ; ; KEITH BALL 6/10/80 ; ISRODN TYA ;SAVE Y REG ON STACK PHA ; INC BUFRLO BNE NOWRP0 ;INCREMENT PTR TO NEXT BvYTE INC BUFRHI ;TO SEND ; ; PATCH TO ROUTINE CHANGED CHECK ; NOWRP0 LDA BUFRLO ;CHECK IF PTR IS WITHIN BUFFER CMP BFENLO ;DO A DOUBLE PRECISION SUBTRACT LDA BUFRHI SBC BFENHI w BCC NOTEND ;BRANCH IF (BUFR) < (BFEN)-MORE TO SEND ; LDA CHKSNT ;TEST IF CHECKSUM ALREADY SENT BNE RELONE ;BRANCH IF ALREADY SENT ; ; SEND CHECKSUM AND SET FLAG ; LDA CHKSUM STA SEROUxT ;PUT CHECKSUM IN SERIAL OUT REG DEC CHKSNT ;SET FLAG TO FF HEX BNE CHKDON ;RETURN ; ; AFTER CHECKSUM SENT AND CAUSE NEXT INTERRUPT THEN CHANGE POKEY ; MASK TO ENABLE TRANSMIT DONE INTERRUPT AND TERMINATE WAIT LOOP. y; RELONE LDA POKMSK ;GET POKEY MASK ORA #$08 ;OR IN ENABLE STA POKMSK STA IRQEN ;ENABLE THE INTERRUPTS ; ; RESTORE REGS AND RETURN ; CHKDON PLA TAY ;RESTOR Y REG PLAz ;RESTORE A REG SAVED IN OS IRQ INT HNDLR RTI ; ; MORE TO SEND. SEND NEXT BYTE POINTED AT BY BUFR. ; NOTEND LDY #0 LDA (BUFRLO),Y ;GET NEXT BYTE STA SEROUT ;PUT IN SERIAL OUT REG ; CLC { ADC CHKSUM ;ADD BYTE TO CHECKSUM ADC #0 STA CHKSUM ; JMP CHKDON ;GO RETURN AND WAIT FOR NEXT BYTE ; ; END OF OUT SERVICE ROUTINE *********************** .PAGE ; **** SERIAL INPUT RE|ADY INTERRUPT SERVICE ROUTINE ****^ H ; ; ; ; AFTER SERIAL RECEIVE IS ENABLED ROUTINE IS USED TO COLLECT ; BYTES FROM THE SERIAL INPUT REG AND PUT THEM IN BUFFER. ; WILL STOP WHEN BUFFER IS FULL. IF A CHECKSUM IS EXPECTED ; }ROUTINE WILL MARK BUFFER FULL AND CONTINUE. WHEN CHECKSUM ; RECEIVED IT WILL CHECK IF = TO CHECKSUM IT WAS MAKING. ; WILL STORE ERRORS FOUND IN STATUS LOCATION. ; ; THE IRQ INTERRUPT HANDLER IN THE OS PUSHES THE USER'S A REGISTER ; ~ ONTO THE STACK BEFORE CALLING THIS ROUTINE. ; ; KEITH BALL 6/11/80 ; ISRSIR TYA ;SAVE Y REG ON STACK PHA ; ; GET STATUS FROM POKEY THEN RESET IT. ; LDA SKSTAT STA SKRES ;IGNORES VALUE- JUST STROBED ; ; CHECK FOR ERRORS ; BMI NTFRAM ;BIT 8 SET IF NO FRAMING ERROR LDY #FRMERR ; STY STATUS ;SET FRAME ERROR STATUS ; NTFRAM AND #$20 ;IF BIT 5 CLEAR THEN FRAME OVER RUN BNE NTOVRN ;BRANCH IF NO OVER RUN LDY #OVRRUN ; STY STATUS ;ELSE SET OVERRUN ERROR STATUS ; ; CHECK IF BUFFER FULL AND THIS IS A CHECKSUM. IF IT IS, THEN CHECK ; IF DATA SENT WAS VALID. ; NTOVRN LDA BUFRFL ;TEST FOR BUFFER FULL (NOT ZERO) BEQ NOTYET ;IF ZERO THEN NOT YET, THIS IS DATA. LDA SERIN ;ELSE THIS IS CHECKSUM CMP CHKSUM ;ARE THEY EQUAL? BEQ SRETRN ;YES,THEN RETURN LDY #CHKERR  ;ELSE SET CHECK SUM ERROR STATUS STY STATUS ; ; SET RECEIVE DONE TO END WAIT LOOP ; SRETRN LDA #$FF ;DONE VALUE STA RECVDN ; ; RESTORE REGS AND RETURN ; SUSUAL PLA TAY ;RESTORE Y REG PLA ;RESTORE A REG RTI ; ; IF BYTE IS DATA, THEN GET HERE. PUT BYTE IN BUFFER AND CHECK IF ; AT END OF BUFFER. ; NOTYET LDA SERIN ;GET DATA BYTE LDY #0 ; STA (BUFRLO),Y ;STORE IT IN THE BUFFER ; CLC ; ADC CHKSUM ;ADD DATA BYTE TO CHECKSUM ADC #0 ; STA CHKSUM ; ; INC BUFRLO ;INCREMENT POINTER TO LOCATION BNE NTWRP1 ;FOR NEXT BYTE INPUT INC BUFRHI ; ; THE PATCH CHANGED THE TEST FOR END OF BUFFER ; NTWRP1 LDA BUFRLO ;DO DOUBLE PRECISION SUBTRACT CMP BFENLO ; LDA BUFRHI ; SBC BFENHI ;CARRY CLEAR IF BORROW BCC SUSUAL ;BR IF (BUFR) < (BFEN)-WITHIN BUFR LIMIT ; ; DONE WITH DATA. SEE IF CHECKSUM TO BE SENT ; LDA NOCKSM ;IF = ZERO THEN A CHECKSUM BEQ GOON ;WILL FOLLOW THE DATA ; LDA #0 ;ELSE NO CHECKSUM TO FOLLOW STA NOCKSM ;CLEAR NO CHECKSUM FLAG BEQ SRETRN ;RETURN AFTER SET RECEIVE DONE FLAG ; ; SET BUFFER FULL AND THEN GO GET CHECKSUM ; GOON DEC BUFRFL ;SET BUFFER FULL FLAG TO FF BNE SUSUAL ;GO RETURN ; ; END OF RECEIVE SERIAL INPUT INTERRUPT ROUTINE********************** MDEND = * HILO MDEND *=$70C .BYTE MDENDL,MDENDH ;SET END ADDR IN FMS PAST RESIDENT DUP SO ; BUFFERS DON'T CLOBBER IT. STAK  = $100 HILO STAK .PAGE ; **** BEGINNING OF NON-RESIDENT PORTION OF DUP ****^ H ; ; NDOS = MDEND+$A00 ;END OF SYS BUFRS AND MINIDUP ; ; ROOM FOR 8 256 BYTE DRIVE BUFFERS & 2 256 BYTE FILE BUFFERS ; DRTST =  9 ;ONE BEYOND MAX DRIVES FOR TEST IN GETDN ; HILO NDOS *=NDOS PAR *=*+40 ;PARAMETER AREA PARH = PAR/256 PARL = (-256)*PARH+PAR LINE *=*+80 ;TYPEIN LINE BUFFER LBUFH =  LINE/256 LBUFL = (-256)*LBUFH+LINE DBUF *=*+$100 ;DATA BUFFER FOR COPY DB1 = DBUF+$80 DB3 = DBUF-3 HILO DBUF HILO DB1 HILO DB3 DBLL = 0 DBLH = 1 ;DATA BUFFER LENGTH=$100 EDBLL = $FA ;DATA BUFFER LENGTH USED IN USEPGM EDBLH = 0 ;MUST BE A MULT OF 125, SECT DATA LENGTH MENUSZ *=*+1 PER *=*+1 UNNO *=*+1 RCNT *=*+1 SSTAT *=*+1 SWDP *=*+5 CSRC *=*+1 CDES  *=*+1 SAVX *=*+1 PTR *=*+1 IPTR *=*+1 CTR *=*+1 T1 *=*+2 BUFLEN = T1 ;SAVE AREA FOR BUFR LEN, USED IN USEPGM STVEC *=*+2 ;A TEMP OF SOME KIND MLT125 = STVEC ;TEMP STORE FOR MULTIPLE OF 125, USEPGM SECSIZ *=*+2 ;USED TO STORE SECTOR SIZE IN BYTES FOR DUP DISK EOFFLG *=*+1 ;ENDFILE FLAG FOR SOURCE IN DUPFIL FTRF *=*+1 ;FIRST TIME READ FLAG USED IN DUPFIL TWODRV = FTRF ;FLAG TO SHOW IF 1 OR 2 DRIVES. USED IN DUPDISK DTH =* HILO DTH EDN .BYTE 'E:',CR EDH = EDN/256 EDL = (-256)*EDH+EDN .PAGE ; **** DOS MENU ****^ H ; ; DMENU .BYTE CLSCR .BYTE 'DISK OPERATING SYSTEM CORVUS A2.0D ',CR .BYTE 'COPYRIGHT 1980 ATARI 4/25/81',CR,CR .BYTE 'A. DISK DIRECTORY I. FORMAT DISK',CR .BYTE 'B. RUN CARTRIDGE J. DUPLICATE DISK',CR .PAGE .BYTE 'C. COPY FILE K. BINARY SAVE',CR  .BYTE 'D. DELETE FILE(S) L. BINARY LOAD',CR .BYTE 'E. RENAME FILE M. RUN AT ADDRESS',CR .BYTE 'F. LOCK FILE N. CREATE MEM.SAV',CR .PAGE .BYTE 'G. UNLOCK FILE O. DUPLICATE FILE',CR .BYTE 'H. WRITE DOS FILES',CR .BYTE CDN,CDN,CDN,CDN,CDN DMEND =* DULEN = DMEND-DMENU HILO DULEN HILO DMENU ; DUJPT .WORD DIRLST,STCAR,CPYFIL,DELFIL,RENFIL,LKFIL,ULFIL .WORD WBOOT,FMTDSK,DUPDSK,SAVFIL,LDFIL,BRUN,MEMSAV .WORD DUPFIL HILO DUJPT DUNUM = 15 ;NUMBER OF FUNCTIONS .PAGE ; **** DISK OPERATING SYS MONITOR ****^ H ; ; DOSOS LDX #$FF HILO DOSOS CLD ;MAKE SURE DECIMAL MODE OFF STX BRKKEY INX STX LOADFG LDA #2 STA LMARGN LDA #39 STA RMARGN ;SET MARGINS LDA POKMSK ;ENABLE BREAK INTERRRUPTS ORA #$80  STA POKMSK STA IRQEN JSR INITIO ;CLOSE FILES ; ; DISK UTILITY MONITOR ; DSKUTL DU1 LDA #DUNUM STA MENUSZ ;SET MENU SIZE. LDA #DUJPTL STA JMPTBL LDA #DUJPTH STA JMPTBL+1 ;SET UP JUMP TABLE ADDRESS ; FALL THRU TO MENU SELECT ; ; ; ; MENU SELECT MONITOR -- VECTORS TO ROUTINE SELECTED FROM MENU. ; SHMEN LDA #DMENUL ;GET MENU ADDRESS STA ICBAL LDA #DMENUH  STA ICBAH LDA #DULENL ;GET MENU LENGTH STA ICBLL LDA #DULENH STA ICBLH JSR DSPMSG ;SHOW MENU ; ; SELECT ITEM FROM MENU .PAGE ; **** FUNCTIONS COME HERE WHEN THEY ARE DONE ****^ H ; MENUSL LDX #$FF ;RESET STACK AT THIS POINT TXS INX STX WCFLAG ;CLEAR WILD-CARD FLAG LDA #SITL ;SELECT ITEM MESSAGE LDX #SITH JSR PRNTMSG LDA #$40 ;MAKE SURE UPPER CASE STA SHFLOK JSR CHRGET ;GO GET KEYBOARD CHAR. ; CMP #CR ;IF CR REDISPLAY MENU BEQ SHMEN ; SEC SBC #'A ;CONVERT ASCII CHAR. TO BINARY # & SUB 1. BMI RANGE ;IF ASCII CHAR NOT A #, GO READ AGAIN CMP MENUSZ ;IS THE # ENTERED > MENU SIZE? BPL RANGE ;IF YES, GO READ AGAIN. ASL A TAY ;SET INDEX TO (MENU # - 1) * 2 LDA (JMPTBL),Y INY STA RAMLO ;GET STRING POINTER LDA (JMPTBL),Y STA RAMLO+1 LDY #1 ;LOAD STRING POINTER INTO REGISTERS LDA (RAMLO),Y ;FOR DSPLIN  TAX DEY LDA (RAMLO),Y JSR DSPLIN ;PRINT MODULES INITIAL STRING JSR SCROL ;SCROLL INPUT WINDOW LDA RAMLO ;INC BY 2 TO POINT PAST STRING POINTER CLC ADC #2  STA RAMLO LDA RAMLO+1 ADC #0 ;CARRY STA RAMLO+1 ;PUT HI BYTE. JMP (RAMLO) ;JUMP TO ROUTINE SELECTED BY MENU. RANGE LDA #NSIL LDX #NSIH JSR DSPLIN ;NO SUCH ITEM MESSAGE JMP MENUSL .PAGE NSI .BYTE 'NO SUCH ITEM',CR ; ; PROMPT FOR MENU SELECTION OR REDISPLAY MENU - RETURN IS IN INVERSE ; SIT .BYTE 'SELECT ITEM OR ',$D2,$C5,$D4,$D5,$D2,$CE .BYTE ' FOR MENU',CR HILO NSI HILO SIT MNSL = MENUSL HILO MNSL .PAGE ; **** DIRECTORY LISTING ROUTINE ****^ H ; ; DIRLST .WORD DLMG JSR GETIC1 JSR USEBUF ;INIT BUFADR & BUFLEN LDX PTR LDA #CR STA PAR-1,X ;ASSURE GOOD TERM LDA PAR-2,X ;LAST CHAR OF SEARCH SPEC CMP #': ;IF COLON, ADD *.* BNE GLF LDA #'* STA PAR-1,X STA PAR+1,X LDA #'. STA PAR,X LDA #CR STA PAR+2,X INX INX INX STX PTR GLF STX SAVX LDX #$20 JSR PIOCB JSR GETFIL JSR PERX LDA #6 ;READ DIR INFO LDX #$10 STA ICAX1,X LDA #OPEN ;OPEN STA ICCOM,X STX CSRC ;COPY SOURCE=DIRECTORY INFO CPX #$10 BNE *+3 JSR CIOCL LDA PTR SEC SBC SAVX CMP #3 ;IF ONLY 3 CHARS, IS 'D:'CR, USE DEFAULT BEQ DLST1 DLST0 JMP PDES ;GO INTO COPY DLST1 LDX SAVX LDA PAR,X CMP  #'D BNE DLST0 JMP PDES1 ;GO INTO COPY WITH DES='E:' .PAGE DLMG .BYTE 'DIRECTORY--SEARCH SPEC,LIST FILE?',CR .PAGE ; **** DELETE FILE ROUTINE ****^ H ; ; DELFIL .WORD DEMG JSR GETIC1 JSR PERX ;EXIT IF PARAM ERRORS ; JSR CHKVER ;BE SURE THAT IT IS VER. 2 DISKETTE ; ; CONTINUE WITH DELETE - ALLOW ONLY FOR DISK DEVICE ID ; LDA PAR ;GET DEVICE CMP #'D ;ONLY ALLOW DELETE FOR D: BEQ DF1 LDA #NDFL LDX #NDFH JSR DSPLIN JMP MENUSL NDF .BYTE 'NOT A DISK FILE',CR HILO NDF DF1 LDX #$10 LDA OPT CMP #'N ;IF OPTION=N, NO QUERY BNE DWQ ;NO, DELETE WITH QUERY LDA #DELETE STA ICCOM,X JSR CIOCL JMP MENUSL DWQ LDA #TYQL LDX #TYQH JSR DSPLIN ;SAY TYPE Y TO DELETE... LDA #0 STA IPTR ;HOW MANY FILES TO SKIP, NONE AT FIRST LDX #$20 ;SET UP DELETE IOCB LDA #DELETE STA ICCOM,X LDA #DB3L STA ICBAL,X LDA #DB3H STA ICBAH,X LDA #'D STA DBUF-3 LDA #': STA DBUF-1 LDA PAR+1 ;DEVICE NUMBER OR : FROM OP INPUT CMP #': BNE *+4 LDA #'1 STA DBUF-2 ;KLUDGE KLUDGE KLUDGE IDRD LDX #$10 LDA #OPEN STA ICCOM,X LDA #6 STA ICAX1,X ;DIR READ OPEN LDA #PARL STA ICBAL,X LDA #PARH STA ICBAH,X  JSR CIOCL LDA #DBUFL STA ICBAL,X LDA #DBUFH STA ICBAH,X LDA #GETREC STA ICCOM,X LDA #0 STA PTR ;HOW MANY FILES WE HAVE SKIPPED ; READ FILENAME FROM DIR, QUERY AND DELETE RDFN LDX #$10 LDA #0 STA ICBLL,X LDA #1 STA ICBLH,X JSR CIOCL ;READ A LINE FROM DIRECTORY LDA DBUF+1 ;IF FILE LINE, THIS IS BLANK CMP #' BNE DELX ;THIS IS FREE BLOCKS LINE INC PTR ;COUNT THIS FILE LDA PTR ;HAVE WE SKIPPED ENUF YET CMP IPTR BMI RDFN ;BR IF NO LDX #0 ;PUT PTR LDY #2 ;GET PTR ;MASSAGE DELETE FILE NAMES MDN1 LDA DBUF,Y CMP #' ;END OF FILENAME BEQ MDN2 STA DBUF,X INX INY CPX #8 BMI MDN1 ;FILENAME IS MOVED, PUT .EXT MDN2 LDA #'. STA DBUF,X INX LDY #10 ;WHERE EXT IS MDN3 LDA DBUF,Y STA DBUF,X INY INX CPY #13 BMI MDN3 STX SAVX ;PUT CR HERE LATER LDA #'? ;FOR QUERY STA DBUF,X INX LDA #CR STA DBUF,X LDA #DB3L LDX #DB3H JSR DSPLIN ;GO ASK ABOUT THIS FILE JSR CHRGET  CMP #'Y BNE RDFN ;GO DO NEXT FILENAME LDA PTR ;NUMBER FILES WE HAVE GONE THRU SO FAR STA IPTR ;IS NEW NUMBER TO SKIP. LDX SAVX LDA #CR STA DBUF,X  LDX #$20 ;DELETE IOCB JSR CIOCL JSR CLOS1 JMP IDRD ;CLOSE AND REOPEN DIR READ FILE DELX JSR CLOS1 ;CLOSE DIR READ FILE JMP MENUSL CLOS1 LDX #$10 LDA #CLOSE  STA ICCOM,X JMP CIOCL ;DO CLOSE AND RETURN TYQ .BYTE 'TYPE ',$22,'Y',$22,' TO DELETE...',CR HILO TYQ DEMG .BYTE 'DELETE FILE SPEC',CR ;LIST .PAGE ; **** COPY FILE ROUTINE ****^ H ; ; CPMG .BYTE 'COPY--FROM, TO?',CR OE .BYTE 'OPTION NOT ALLOWED',CR HILO OE ; ; ; ; ; WCFLAG *=*+1 WCSKP1 *=*+1 WCSKP2 *=*+1 WCBUFL = 20 WCBUF *=*+WCBUFL WCOPYM .BYTE ' COPYING---' WCBUF2 .BYTE 'DN:' *=*+WCBUFL-3 CPYFIL .WORD CPMG ;COPY FILE PROMPT JSR GETIC1 ;GET SOURCE DEVICE, ETC. LDA PTR STA SAVX LDA PAR ;GET 1ST CHAR. OF DEVICE CMP #'D ;TEST IF IT IS THE DISK BNE  JMPNWC ;BRANCH IF NOT THE DISK (THEN USE OLD CODE) LDX #0 ;LOOK AT SOURCE FILE SPEC. JSR LOOKWC ;LOOK FOR WILDCARDS IN FILE SPEC. BEQ CPYFL1 ;BRANCH IF WILDCARDS USED IN DISK SPEC. JMPNWC JMP  NOTWC ;USE OLD CODE CPYFL1 LDA #$80 ; ; WCINIT STA WCFLAG ;SET 'WILDCARD' MODE (COPY-FILE OR DUPLICATE-FILE) LDA #0 STA WCSKP1 ; WCOPYL LDA #0 STA WCSKP2 LDX #$10 ;OPEN DIRECTORY LDA #6 STA ICAX1,X LDA #OPEN STA ICCOM,X LDA #.LOW.PAR STA ICBAL,X LDA #.HIGH.PAR STA ICBAH,X JSR CIOCL ; ; WCOPYR LDA #GETREC ;READ DIRECTORY STA ICCOM,X LDA #WCBUFL STA ICBLL,X LDA #0 STA ICBLH,X LDA #.LOW.WCBUF STA ICBAL,X LDA #.HIGH.WCBUF STA ICBAH,X JSR CIOCL ; LDA WCBUF ;IF 1ST CHAR. OF DIR READ IS A #-IT IS TIME TO QUIT CMP #'0 BCC WCGOT CMP #': BCS WCGOT ; LDA #CLOSE ;ALL DONE -- NORMAL EXIT OF WILDCARDED COPY STA  ICCOM,X JSR CIOCL JMP MENUSL ; ; WCGOT LDA WCSKP1 ;IF ALREADY COPYIED OR SKIPPED THIS ; FILE, THEN IGNORE IT AND REREAD DIRECTORY CMP WCSKP2 BEQ SKIP1 ; INC WCSKP2 BNE WCOPYR ; SKIP1 INC WCSKP1 ; LDA #CLOSE ;CLOSE DIRECTORY READ FILE STA ICCOM,X JSR CIOCL ; ; LDY #2 ;DON'T COPY .SYS FILES SYSLOP LDA WCBUF+10,Y CMP DOTSYS,Y BNE  NOSYS DEY BPL SYSLOP BMI WCOPYL ; DOTSYS .BYTE 'SYS' ; NOSYS LDY #'1 ;CALC SOURCE DRIVE NUMBER LDA PAR+1 CMP #': BEQ WCGOT1 TAY WCGOT1 STY WCBUF2+1 ; ;  LDX #2 ;COMPRESS SPACES, ADD ':', ADD 'CR' LDY #3 ; COMPR1 LDA WCBUF,X CMP #' BEQ COMPR2 STA WCBUF2,Y INY ; COMPR2 INX CPX #10 BNE COMPR1 ;  LDA WCBUF,X CMP #' BEQ COMPR5 LDA #'. STA WCBUF2,Y INY COMPR3 LDA WCBUF,X CMP #' BEQ COMPR4 STA WCBUF2,Y INY COMPR4 INX CPX #13  BNE COMPR3 ; COMPR5 LDA #CR STA WCBUF2,Y ; ; LDA #.LOW.WCOPYM ;PRINT 'COPYING---DEV:FILENAME.EXT' MSG LDX #.HIGH.WCOPYM JSR DSPLIN ; BIT WCFLAG BVC WCOPY ;BR TO MIDDLE OF DUP FILE ROUTINE IF DUPING FILES ; LDX #$10 ;SET UP BUFR ADDR TO POINT TO WILDCARDED FILENAME LDA #.LOW.WCBUF2 STA ICBAL,X LDA #.HIGH.WCBUF2 STA ICBAH,X JMP WCDUPS ; WCOPY JSR USEPGM ;SET BUFFER SIZES LDX #$10 ;OPEN COPY SORCE FILE LDA #OPEN STA ICCOM,X LDA #4 STA ICAX1,X LDA #.LOW.WCBUF2 STA ICBAL,X LDA  #.HIGH.WCBUF2 STA ICBAH,X STX CSRC JSR CIOCL ; LDX #$20 JSR PIOCB ;GET COPY DESTINATION FILE LDA PTR ;SAVE PTR,IPTR-MIGHT REPT GET 2ND FILENAME MANY TIMES PHA LDA IPTR PHA JSR GETFIL ;GET 2ND FILE NAME TO PAR PLA ;RECOVER IPTR,PTR STA IPTR PLA STA PTR LDX SAVX LDA PAR,X CMP #'D  BEQ WCOPY0 JMP PDES ;JUMP TO OLD COPY-FILE CODE IF NOT A DISK DESTINATION ; WCOPY0 LDY #'1 ;CALCULATE DESTINATION DRIVE # LDA PAR+1,X CMP #': BEQ WCOPY1 ; TAY WCOPY1 CPY  WCBUF2+1 BNE WCOPY2 JSR CLOSX ;CAN NOT COPY TO SAME DRIVE NUMBER -- ERROR & EXIT ; JMP ODMS ; ; WCOPY2 LDX #$20 STY WCBUF2+1 ;CHANGE FILESPEC TO DESTINATION LDA #.LOW.WCBUF2  STA ICBAL,X LDA #.HIGH.WCBUF2 STA ICBAH,X JMP OPDES1 ;CONTINUE INTO OLD COPY-FILE CODE ; ; NOTWC = * LDX #$20 ;IOCB 3 JSR PIOCB JSR GETFIL ;GET SECOND FILENAME ; ; MAKE SURE DESTINATION IS NOT DOS.SYS ; LDX SAVX ;ENTRY-INDEX TO DEST FILE SPEC JSR TSTDOS ;WON'T RETURN IF IS DOS.SYS ; LDX SAVX JSR LOOKWC BNE NWCIND ;BRANCH IF NO WILDCARDS IN DESTINATION LDA #NWAL LDX #NWAH JSR DSPLIN JMP MENUSL NWA .BYTE 'WILD CARDS NOT ALLOWED IN DESTINATION',CR HILO NWA NWCIND = * JSR PERX ;IF PARAM ERRS, EXIT JSR USEPGM ;ASK USER IF CAN USE PGM AREA OR DATA BUFFER PSRC = * LDA PAR ;GET 1ST LETR OF PARAM CMP #'K BEQ ODMS ;K: GETS 'OPTION DOESNT MAKE SENSE' FOR NOW CMP  #'C BEQ ODMS ;C: GETS 'OPTION DOESNOT MAKE SENSE' FOR NOW CMP #'E ;E: AS SOURCE IS SPECIAL BNE OPSRC ;IF NO THEN OPEN SOURCE FILE LDX #0 STX CSRC JMP PDES OPSRC  CMP #'S BEQ ODMS ;S: AS SOURCE GETS O.D.M.S. FOR NOW ; ; OPEN SOURCE FILE ; LDX #$10 LDA #OPEN STA ICCOM,X LDA #4 ;OPEN IN STA ICAX1,X STX CSRC  CPX #$10 BNE *+33 JSR CIOCL ;OPEN SOURCE FILE HERE ; ; READY FOR OPEN OF DESTINATION ; PDES LDX SAVX LDA PAR,X ; CMP #'K ;IS DEST KEYBOARD? BEQ ODMS ;YES, THEN CAN'T DO IT ; CMP #'E ;CHECK FOR SPECIAL CASE BNE OPDES ;IF NOT PDES1 LDA #0 ;SPECIAL CASE - DONT OPEN, USE EXISTING IOCB STA CDES JMP DOCPY ODMS LDA #OEL  LDX #OEH ;SAY OPTION NOT ALLOWED JSR DSPLIN JSR CLOSX ;CLOSE IOCB 1 & 2 JMP MENUSL ; OPDES CMP #'C BEQ ODMS ;C: GETS 'OPTION DOESNOT MAKE SENSE' FOR NOW LDX OPT  ;GET 2ND FILE OPTION ; CPX #'A ;APPEND TO DISK FILE BNE OPDES1 CMP #'D BNE ODMS LDA #9 BNE OPDES3 OPDES1 LDA #8 OPDES3 LDX #$20 STA ICAX1,X ;OPEN TYPE OUT LDA #OPEN STA ICCOM,X ;OPEN STX CDES JSR CIOCL LDA #0 STA ICAX2,X ;COPY FROM CSRC TO CDES DOCPY LDA #GETCHR GC1 LDX CSRC LDY CDES STA  ICCOM,X LDA #PUTCHR STA ICCOM,Y LDA BUFADR ;ADDRESS OF BUFFER - EITHER STA ICBAL,X ;PGM AREA (MEMLO) OR DATA BUFFER (DBUF) STA ICBAL,Y LDA BUFADR+1 ;BUFADR IN LSB,MSB ORDER STA ICBAH,X STA ICBAH,Y CLOOP LDX CSRC LDA BUFLEN ;LENGTH OF BUFFER ADDRESSED STA ICBLL,X ;BY BUFADR LDA BUFLEN+1 ;BOTH BUFADR & BUFLEN ARE ASSIGNED STA ICBLH,X  ;IN SUBROUTINE USEPGM JSR CIO ;READ FROM INPUT STY SSTAT LDX CDES LDY CSRC LDA ICBLL,Y STA ICBLL,X LDA ICBLH,Y STA ICBLH,X ORA ICBLL,Y  ;IF SOURCE FILE LENGTH = 0 BEQ CKRS ;DONT DO WRITE JSR CIOCL ;WRITE, ABORT IF ERROR CKRS LDA SSTAT ;GET READ OPERATION STATUS BACK BPL CLOOP ;IF OK, GO READ SOME MORE CMP #$88 ;EOF STATUS BEQ *+5 JMP CIOER ;IF NOT, ABORT CLOC LDX CSRC BEQ DU4 ;IF E:, DONT CLOSE ; ;CLOSE SOURCE FILE ; LDA #CLOSE STA ICCOM,X JSR CIO DU4 LDX  CDES BEQ DU3 ;IF DES=E: LDA #CLOSE STA ICCOM,X JSR CIO DU3 LDX CDES BNE DU6 LDA #.LOW.DDSK+1 LDX #.HIGH.(DDSK+1) JSR PRNTMSG ;PRINT A CR BEFORE SELECT OR WILDCARD PROMPT DU6 = * ; BIT WCFLAG BPL DU5 JMP WCOPYL ;BRANCH BACK TO WILD CARD LOOP DU5 JMP MENUSL .PAGE ; **** RENAME FILE ROUTINE ****^ H ; ; ; RENAME SETS UP IOCB #1 WITH THE OLD FILE NAME AND THE BUFFER ADDRESS ; POINTS TO THE NEW FILE NAME. THE NEW FILE SPECIFICATION CANNOT HAVE ; A DEVICE ID. THE DEVICE ID IS THE SAME AS SPECIFIED FOR THE OLD FILE ; EG D2:ABC.S2,QQQ.R3 THIS RENAMES ABC.S2 ON DRIVE #2 TO QQQ.R3 ; ; RENFIL .WORD RNMG JSR GETIC1 ;GET OLD FILE SPEC & PUT ADDR IN IOCB JSR GETNAME ;GET NEW FILE NAME JSR PERX ;EXIT IF PARAMETER ERRORS ; JSR CHKVER ;MAKE SURE VER 2 DISKETTE ; ; CONTINUE WITH RENAME ; LDA #RENAME LDX #$10 STA ICCOM,X JSR CIOCL JMP MENUSL RNMG .BYTE 'RENAME - GIVE OLD NAME, NEW',CR ; ;******************* SUBROUTINE ******************* ; ; MAKE SURE THIS IS A VERSION 2 FORMAT DISK ; CHKVER LDY #1 ;ASSUME DRIVE 1- GET DRIVE # LDA PAR+1 ;TEST CHAR 2 OF FILE SPEC FOR SEMICOLON CMP #': ;IF IS, USING DEFAULT DRIVE (1) BEQ DRV1 ;IT IS, SO SAVE DRIVE # AND #$0F ;ELSE CHAR 2 IS ASCII REP OF DRIVE # TAY ;CONVERT TO BINARY & SAVE IT DRV1 STY UNNO ;SAVE DRIVE # ; JMP TSTVER2 ;TEST FOR VER 2 DISK- WON'T RETURN IF NOT ; .PAGE ; **** FORMAT DISK ROUTINE ****^ H ; ; FMTDSK .WORD WHD JSR GETLIN JSR GETDN CLC ADC #'0 STA DDSK STA CDSK JSR PERX LDA #VFML ;QUERY TO VERIFY DRIVE NUMBER LDX #VFMH JSR DSPLIN JSR CHRGET CMP #'Y ;SEE IF OK BNE FMX LDA #FDPL LDX #$10 STA ICBAL,X LDA #FDPH  STA ICBAH,X LDA #FORMAT STA ICCOM,X JSR CIOCL ;CALL CIO TO DO FORMAT FMX JMP MENUSL ;EXIT. WHD .BYTE 'WHICH DRIVE TO FORMAT?',CR VFM .BYTE 'TYPE ',$22,'Y',$22,' TO FORMAT DISK ' DDSK *=*+1 .BYTE CR FDP .BYTE 'D' CDSK *=*+1 .BYTE ':',CR HILO WHD HILO VFM HILO FDP .PAGE ; **** START CARTRIDGE ROUTINE ****^ H ; ; SYVBL = SYSVBV HILO SYVBL XTVBL = XITVBV HILO XTVBL STCAR .WORD SCMG ;NO MSG, PRINT A ROMTST = $BFFD LDY ROMTST ;TEST IF RAM OR OTHER LDA #$AA ;PATTERN #1 STA ROMTST CMP ROMTST BNE NOTRAM ;BRANCH IF NOT RAM LDA #$55 ;PATTERN #2 STA ROMTST CMP ROMTST BNE NOTRAM ;BRANCH IF NOT RAM ; STY ROMTST ;THERE IS VALID RAM - SAY NO CART NOCART LDA  #NCAL LDX #NCAH ;SAY NO CART JSR DSPLIN JMP MENUSL ; ; CHECK IF ROM OR EMPTY ADDRESS SPACE ; NOTRAM LDA $BFFC ;KNOWN ROM ZERO BYTE BNE NOCART ;BRANCH IF EMPTY ADDRESS SPACE ;  TAX ;SINCE EMPTY ADDRESS SPACE GIVES A RANDOM CKCART LDA ROMTST ;VALUE, TEST THE SAME LOCATION MANY TIMES. BEQ NOCART ;BRANCH IF NO CARTRIDGE CMP ROMTST BNE NOCART ;BRANCH IF NO CARTRIDGE INX BNE CKCART ;LOOP BACK ; ; ; RESET VERTICAL BLANK VECTORS BEFORE ENTERING CART ; JSR INITIO LDA #6 SET VVBLKI LDX #SYVBLH HI BYTE LDY #SYVBLL  JSR SETVBV LDA #7 ;SET VVBLKD LDX #XTVBLH LDY #XTVBLL JSR SETVBV JMP CLMJMP .PAGE NCA .BYTE 'NO CARTRIDGE' SCMG .BYTE CR HILO NCA ; ; ; ******* RUN AT ADDRESS *******^ H ; ; ; BRUN .WORD BRMG JSR GETLIN JSR GETNO JSR PERX STA RAMLO STX RAMLO+1 LDA CTR CMP #4 BEQ MOUT1 ;RETURN TO MENU IF NO RUN ADDRESS GIVEN JSR INITIO ;CLOSE ALL IOCB'S, THEN REOPEN S/E JMP LMTR ;LOAD MEM.SAV & JUMP TO ADDRESS ; ; BRMG .BYTE 'RUN FROM WHAT ADDRESS?',CR .PAGE ; **** CREATE MEM.SAV FILE ON DISK ****^ H ; ; MEMS .BYTE 'TYPE ',$22,'Y',$22,' TO CREATE MEM.SAV',CR MEMSAV .WORD MEMS JSR CHRGET ; GET CHAR (CR) CMP #'Y BNE MOUT ;BRANCH IF USER'S ANSWER NOT A Y JSR MEMSVQ ;TRY TO OPEN MEM.SAV BMI MCONT ; IF FILE DOESN'T EXIST THEN JUMP LDA #MEMSGL ; ELSE 'MEMORY.SAVE' AREADY EXIST LDX #MEMSGH ; JSR DSPLIN ; DISPLAY THIS FACT MOUT JSR CLOSX ; EXIT AFTER CLOSING IOCB1 MOUT1 JMP MENUSL ; ; ; WRITE MEMORY.SAVE TO DISK ; MCONT JSR MWRITE ; WRITE FILE BPL MOUT MERR JMP CIOER1 ; DISPLAY ERROR ; MEMSG .BYTE 'MEM.SAV FILE ALREADY EXISTS',CR HILO MEMSG .PAGE ; **** WRITE DOS & DUP ****^ H ; ; WBOOT .WORD DOSDRV ;ADDRESS OF DRIVE # PROMPT ; ; RETREIVE DRIVE NUMBER FROM USER. ; JSR GETLIN ;GET INPUT JSR GETDN ;GET DRIVE AS NUMBER, VERIFY IT JSR PERX ;EXIT IF ERROR STA UNNO ;SAVE IT FOR TSTVER2 ORA #'0 ;TURN BACK TO ASCII REP STA DS+1 ;STORE IN DOS.SYS FILE SPEC STA QWMG+31 ;& IN PROMPT ; JSR TSTVER2  ;TEST IF VERSION 2 DISK - IF ISN'T WON'T RETURN ; ; ASK USER IF CAN WRITE DOS & DUP TO SPECIFIED DRIVE ; LDA #QWMGL ;PRINT PROMPT LDX #QWMGH JSR DSPLIN JSR CHRGET CMP #'Y BNE WBX ;EXIT UNLESS Y ; ; TELL USER WRITING DOS FILES AND WRITE DOS.SYS FIRST- JUST OPEN IT. ; LDA #WBMGL LDX #WBMGH JSR DSPLIN ; LDA #OPEN LDX #$10 ;OPEN DOS.SYS ON IOCB #1 STA ICCOM,X ;WILL CAUSE FMS TO REWRITE BOOT SECTOR LDA #DSL ;& A COPY OF DOS.SYS STA ICBAL,X LDA #DSH STA ICBAH,X LDA #8 STA ICAX1,X JSR CIOCL  ;DO OPEN, IF ERROR GOTO MENU ; LDX #$10 LDA #CLOSE STA ICCOM,X JSR CIOCL ;DONE CLOSE IT. ; ; WRITE DUP.SYS - SWAP AREA FILE ; LDX #11 ;MOVE 11 CHARS MDUPBL LDA DUPSYS-1,X STA PAR-1,X ;MOVE FILE NAME TO PARAMETER LIST DEX BNE MDUPBL LDA DS+1 ;GET DRIVE NUMBER STA PAR+1 ;PUT IT IN DUP.SYS FILE SPEC ; STX PTR LDX #$10 JSR PIOCB ;PUT FILE NAME POINTER IN IOCB LDA #DTHL STA LDST LDA #DTHH STA LDST+1 LDA #.LOW.NMDUP STA LDND LDA #LENL STA WDRL+1 LDA #LENH  STA WDRH+1 LDA #.HIGH.NMDUP STA LDND+1 PHA ;NO /A LDA #.LOW.DOSOS STA RUNAD LDA #.HIGH.DOSOS STA RUNAD+1 ;SET DUP.SYS RUN ADDRESS DEC  RUNQ+1 ;SET RUN FLAG JMP NRUNAD ;WRITE DUP.SYS WBX JMP MENUSL DOSDRV .BYTE 'DRIVE TO WRITE DOS FILES TO?',CR WBMG .BYTE 'WRITING NEW DOS FILES',CR HILO WBMG .PAGE QWMG .BYTE 'TYPE ',$22,'Y',$22,' TO WRITE DOS TO DRIVE .',CR HILO QWMG DS .BYTE 'D1:DOS.SYS',CR HILO DS WVD .BYTE 'ERROR - NOT VERSION 2 FORMAT.',CR HILO WVD .PAGE ; **** TEST FOR VERSION 2 FORMAT - SUBROUTINE ****^ H ; ; ; ; SUBROUTINE - TSTVER2 ; ; READS THE DISK'S VTOC AND CHECKS IF VERSION BYTE IS SET AS 2. ; ; ENTRY - DRIVE # STORED IN UNNO ; EXIT - RETURNS ONLY IF IS A VERSION 2 DISK ; ELSE DOES AN ERROR EXIT BACK TO MENU ; CALLS - DRVSTAT AND RVTOC ; CALLED BY - DELFIL, RENFIL, WBOOT. ; ; ; GET DRIVE TYPE SO KNOW CORRECT SECTOR SIZE - NEEDED FOR RVTOC ; TSTVER2 = * LDY #0 ;GET DRIVE TYPE IN BUFL STY SECSIZ ;ASSUME 256 - NEEDED BY RVTOC INY STY SECSIZ+1 LDA UNNO ;GET DRIVE # JSR DRVSTAT ;FIND OUT TYPE - CARRY FLAG BCS OKTYP ;BRANCH IF 256 TYPE LDA  #$80 ;ELSE SET AS 128 BYTE DEVICE STA SECSIZ LSR SECSIZ+1 ;CHANGE HI BYTE FROM 01 TO 00 ; ; READ THE VTOC & CHECK IF VERSION 2 ; OKTYP JSR RVTOC ;READ IN VTOC TO DBUF LDA DBUF ;1ST BYTE IS VERSION # CMP #2 ;IS IT VERSION 2? BEQ SMVRS ;YES, SAME VERSION - RETURN ; ; NOT A VERSION 2 DISK - PRINT MSG & GOTO MENU ; LDA #WVDL ;ELSE, NOT SAME VERSION LDX #WVDH ;PRINT INCOMPATIBLE MSG JSR DSPLIN ; JMP MENUSL ;GOTO MENU ; ; DISK IS VERSION TWO SO RETURN ; SMVRS RTS ;RETURN .PAGE ; **** LOAD USER FILE FUNCTION ****^ H ; ; LDFIL .WORD LFMG  JSR GETIC1 LDA #0 LDX OPT STA OPT CPX #'N ;IS OPTION N FOR DON'T LOAD AND GO? BNE NOTN ;BRANCH IF NOT DEC OPT NOTN JSR PERX JSR LOAD CPX #0 ;PROCESS LOAD SUBR RESPONSE BEQ LDFX ;BRANCH IF LOAD WAS OK CPX #3 BEQ NLF ;IF BAD LOAD FILE TYA ;OTHERWISE WE GOT A CIO ERROR JMP CIOER ;GO SAY WHAT IT IS NLF LDA #BLFL LDX #BLFH JSR DSPLIN ;BAD LOAD FILE MSG JSR CLOSX ;CLOSE THE FILE LDFX JMP MENUSL ;EXIT BLF .BYTE 'BAD LOAD FILE',CR HILO BLF LFMG .BYTE 'LOAD FROM WHAT FILE?',CR .PAGE ; **** LOCK & UNLOCK FILE COMMANDS ****^ H ; ; LKFIL .WORD LKMG ;DO LOCK JSR GETIC1 JSR PERX LDA #LOCK LDX #$10 STA ICCOM,X JSR CIOCL JMP MENUSL LKMG .BYTE 'WHAT FILE TO LOCK?',CR ; ULFIL .WORD ULMG ;DO UNLOCK JSR GETIC1 JSR PERX LDA #UNLOCK LDX #$10 STA ICCOM,X JSR CIOCL JMP MENUSL ULMG .BYTE 'WHAT FILE TO UNLOCK?',CR .PAGE ; **** DUPLICATE DISK ROUTINE ****^ H ; ; DDMG .BYTE 'DUP DISK-SOURCE,DEST DRIVES?',CR OK .BYTE 'TYPE ',$22,'Y',$22,' IF OK TO USE PROGRAM AREA',CR HILO OK CMSI .BYTE 'CAUTION: A ',$22,'Y',$22,' INVALIDATES MEM.SAV.',CR HILO CMSI ; ; RVTOC READS VOLUME TABLE OF CONTENTS SECTOR ; RVTOC LDA #1 STA DSHI ;READ VTOC SECTOR LDA #$68 STA DSLO  JSR SETBUFL ;SET BUFL FOR RSEC1 LDA #DBUFH STA DBUFHI LDA #DBUFL STA DBUFLO ;POINT DCB AT DBUF JSR RSEC1 LDA #0 STA PTR LDA DBUF+$A  STA CSRC ;BYTE OF ALLOC MAP LDA #8 STA IPTR ;COUNT BITS IN BYTE LDA #0 STA DSHI ;POINT TO SECTOR ONE LDA #1 STA DSLO RTS ; ; DUPDSK .WORD DDMG  LDA #0 ;ASSUME SINGLE DRIVE STA TWODRV ;CLEAR FLAG JSR GETLIN JSR GETDN STA UNNO ;UNIT NO FOR READ JSR GETDN STA CDES ;CDES IS THE DEST DRIVE #  JSR PERX ; ; DETERMINE THE DRIVE TYPES OF THE SOURCE AND DESTINATION DRIVES ; IF THEY ARE NOT THE SAME THEN ERROR - PRINT MSG AND GOTO MENU. ; IF THEY ARE THE SAME THEN SET SECSIZ AS LENGTH OF NON-BOOT ; SECTORS OF DEVICE- USED IN SETBUFL. ; LDA #$80 ;ASSUME SOURCE IS 128 BYTE/SECTOR STA SECSIZ ;SECSIZ IN LSB,MSB ORDER LDA #0 STA SECSIZ+1 ; LDA UNNO ;CHECK SOURCE FIRST, DO STATUS TEST JSR DRVSTAT ;SETS CARRY IF 256, 128 THEN CARRY CLR BCC ONE28 ;BRANCH IF 128 DEVICE LDX #0 ;ELSE SET SECSIZ AS 256 BYTES STX SECSIZ INX STX SECSIZ+1 ; ; CHECK STATUS ON DESTIN ATION AND SEE IF COMPATIBLE ; ONE28 LDA CDES ;DO STAUS ON DEST JSR DRVSTAT BCC IS128 ;128,YES TEST FOR 128 IN SECSIZ BIT SECSIZ ;ELSE CHK FOR 256 IN SECSIZ BPL SAME ;BRANCH IF DE S & SRC ARE 256 ; ; NOT THE SAME THEN PRINT MSG AND GOTO MENU. ; INCOMP LDA #NCDRL ;PRINT INCOMPATIBLE DRIVE LDX #NCDRH ;MSG JSR DSPLIN JMP MENUSL ;GOTO MENU ; ; 128 BYTE CHECK ; IS128 B IT SECSIZ ;IF LSB NOT 80 HEX THEN 256 SRC BPL INCOMP ;AND THEN INCOMPATIBLE ; ; CHECK IF TWO DRIVE OR SINGLE DRIVE DUP ; SAME LDA UNNO CMP CDES ;IF BOTH UNITS THE SAME BEQ SDD ;SINGLE DRIVE DUP LDX #IBDH LDA #IBDL JSR DSPLIN ;PROMPT TO INSERT BOTH DISKS JSR CHRGET DEC TWODRV ;SET TWO DRIVE FLAG BMI DODKDP ;GO DUP DISK .PAGE IBD .BYTE  'INSERT BOTH DISKS, TYPE RETURN',CR HILO IBD NCDR .BYTE 'ERROR - DRIVES INCOMPATIBLE.',CR HILO NCDR ; ; ;USED BY BOTH SINGLE & DOUBLE DRIVE DUP. WILL NOT ASK TO SWAP IF 2 DRIVE ;FLAG (TWODRV) IS SET. ;IF THE TWO DRIVE FLAG IS CLEAR WILL ;FILL FROM SOURCE DISK, SWAP, EMPTY, SWAP, REPEAT. ; SDD LDA #ISDL ;TELL USER TO INSERT SOURCE LDX #ISDH ;FOR INITIAL READ - USED ONLY FOR SINGLE JSR DSPLIN ;DRIVE DUPLICATE JSR CHRGET DODKDP LDA #NMDUPL ;SET BUFFER AT END OF DUP STA STVEC LDA #NMDUPH STA STVEC+1 ; ; BUFFER BOTTOM MOVES FROM NMDUP TO MEMTOP ; SET END OF BUFFER TO MEMTOP MINUS 1 SECTOR IN BYTES. ; WHEN BUFFER BOTTOM IS LESS THAN OR EQUAL TO BUFFER END, AT ; LEAST ONE MORE SECTOR WILL FIT IN MEMORY. ; LDA MEMTOP ;SECSIZ IS LENGTH OF NON-BOOT SECTORS FOR DEVICE SEC SBC SECSIZ ;T1 IS END OF BUFFER STA  T1 LDA MEMTOP+1 SBC SECSIZ+1 STA T1+1 ;T1 IS MEMTOP MINUS SECTOR SIZE. ; ;SEE IF ROOM FOR AT LEAST ONE SECTOR! ; LDA T1 ;DO DOUBLE PRECISION TEST CMP STVEC ;TO SEE IF ROOM LDA T1+1 ;IF T1 IS = STVEC THEN ENUF ROOM SBC STVEC+1 ;FOR ONE SECTOR BCS ENUF ;BRANCH IF (T1)>=(STVEC) NORM LDA #NRML LDX #NRMH JSR DSPLIN JMP MENUSL ; ENUF JSR CKMEM ;SEE IF OK TO USE USER AREA LDA #0 STA OPT ;SET UP FOR READ HERE FIRST PASS JSR RVTOC ;READ VTOC LDA DSLO ;COPY INITIAL WRITE POINTERS STA SWDP ;TO INITIAL READ POINTERS LDA DSHI STA SWDP+1 LDA PTR STA SWDP+2 LDA IPTR STA SWDP+3 LDA CSRC STA SWDP+4 JMP LRS1 ;SKIP FIRST READ PROMPT ; ;READ FROM SOURCE DISK TIL BUF FULL OR END OF DATA. ; DORD LDA #0 ;FLAG WE ARE READING STA OPT BIT TWODRV ;TEST FOR 2 DRIVES BMI LRS1 ;YES, SKIP THE SWAP LDA #ISDL ;INSERT SRC DISK LDX #ISDH XBLK JSR DSPLIN JSR CHRGET ; ;SWAP POINTERS TO WHERE WE ARE ; LRS1 JSR DOSWDP ;SWAP SECTOR AND BITMAP POINTERS ; ;LOOP READING/WRITING SECTORS TO BUFFER AREA ; LRS JSR SETBUFL ;SET BUFL TO LENGTH OF THIS SECTOR JSR AAM ;ADVANCE ALLOCATION MAP BMI ASPT ;IF FREE, ADV SECTOR POINTER AND TRY AGIN BIT OPT ;SEE WHAT MODE BMI DOW ;BR IF WRITE JSR RSEC1  ;DO READ JMP IOD DOW JSR DKWRT ;DO WRITE IOD LDA DBUFLO ;ADVANCE BUFFER POINTER CLC ADC BUFL ;ADD SECTOR SIZE TO BOTTOM OF BUFFER STA DBUFLO ;SO POINT TO NEXT FREE BLOCK  LDA DBUFHI ADC BUFL+1 ;BUFL IS LENGTH OF CURRENT SECTOR STA DBUFHI ASPT JSR ASP ;GO ADVANCE SECTOR POINTER BEQ STDD1 ;ALL SECTORS DONE, SWAP TO DEST DISK LDA T1 ;SEE IF ROOM FOR ANOTHER CMP DBUFLO ;SECTOR BELOW MEMTOP LDA T1+1 SBC DBUFHI BCS LRS ;BRANCH IF (DBUF)<=(T1) - ROOM FOR MORE. ; ;SWAP DISKS AND CONTINUE ; STDD LDA OPT BMI DORD  ;IF WAS WRITE, GO READ STDD2 DEC OPT ;CHANGE TO WRITE BIT TWODRV ;ARE 2 DRIVES BEING USED? BMI LRS1 ;YES, SKIP THE SWAP LDA #IDDL ;INSERT DEST DISK LDX #IDDH JMP  XBLK ;GO DO WRITE STDD1 LDA OPT ;END OF DATA BPL STDD2 ;IF READ GO WRITE JMP MENUSL ;IF WRITE WE ARE DONE ; ;DOSWDP - EXCHANGE CURRENT AND SAVED BITMAP&SECTOR POINTERS ; ALSO INIT BUFFER POINTER ; DOSWDP LDY #4 SWLOP LDA SWATL,Y STA RAMLO LDA SWATH,Y STA RAMLO+1 ;GET ADDRESS FROM TABLE TO RAMLO LDX #0 LDA (RAMLO,X) ;GET WHATS THERE PHA LDA SWDP,Y  STA (RAMLO,X) PLA STA SWDP,Y DEY BPL SWLOP LDA STVEC STA DBUFLO LDA STVEC+1 STA DBUFHI RTS ; ; WHAT A MESS ; HILO DSLO HILO DSHI ! HILO PTR HILO IPTR HILO CSRC .PAGE SWATL .BYTE DSLOL,DSHIL,PTRL,IPTRL,CSRCL SWATH .BYTE DSLOH,DSHIH,PTRH,IPTRH,CSRCH ; ; NRM .BYTE 'NOT ENOUGH ROOM',CR ISD .BYTE 'INSERT SOURCE DISK,TYPE RETURN"',CR IDD .BYTE 'INSERT DESTINATION DISK,TYPE RETURN',CR HILO NRM HILO ISD HILO IDD ; ; ; AAM - ADVANCE ALLOCATION MAP ONE BIT. ; RETURN MINUS IF FREE. ; AAM ASL CSRC ;NEXT BIT OF ALLOC MAP DEC# IPTR BNE CBIT ;IF DONE WITH THIS BYTE INC PTR ;GET NEXT ONE LDX PTR LDA DBUF+$A,X ;VTOC IS AT DBUF & BIT MAP STARTS IN 10TH BYTE STA CSRC LDA #8 STA I$PTR CBIT LDA CSRC ;CHECK THE BIT RTS ; ; ; ASP - ADVANCE SECTOR POINTER IN DCB. ; RETURN EQ IF AT END. ASP LDA DSLO ;SEE IF END CMP #208 BNE NXS LDA DSHI CMP #2 B%EQ ASPX ;ALL DONE NXS INC DSLO BNE ASPX INC DSHI ASPX RTS ; ; RSEC1 - READ A SECTOR WHOSE NUMBER IS IN DCB ; RSEC1 LDA UNNO STA DUNIT CLC ;TELL DISK HANDLER DOING A GE&T SECTOR PHP ;SAVE FLAG JMP CLDKH ; ; DKWRT - WRITE A SECTOR ; DKWRT LDA CDES ;PUT DEST UNIT # STA DUNIT ;IN DCB SEC ;TELL DISK HANDLER DOING WRITE SECTOR PHP' ;SAVE FLAG CLDKH LDA #2 ;SET RETRY COUNT STA RCNT CLD1 LDX #1 ;SET DRIVE TYPE- ASSUME 128 BIT BUFL ;TEST FOR 128 BMI NOT256 ;IF IS BRANCH INX ( ;ELSE SET FOR 256 NOT256 PLP PHP ;SET ACTION FLAG & SAVE IT FOR RETRY JSR BSIOR ;GOTO FMS DISK HANDLER BPL DRTS ;RETURN IF GOOD STATUS ; DEC RCNT ;ELSE SEE IF MORE RETRIES ) BPL CLD1 ;YES, DO AGAIN JMP CIOER1 ;CIO ERROR, GO SAY WHICH DRTS PLP ;EVEN OUT STACK RTS ;RETURN ; ; CKMEM - ASK IF OK TO USE USER AREA ; CKMEM LDA WARMST ;IF MEMO*RY WAS INTACT BEQ CPTR1 ;QUERY TO BOMB IT LDA #OKL LDX #OKH ;PRINT PROMPT JSR DSPLIN LDA #CMSIL ;PRINT CAUTION MSG LDX #CMSIH ;Y RESPONSE WILL INVALIDATE MEM.SAV + JSR DSPLIN JSR CHRGET CMP #'Y ;TEST FOR OK TO BOMB USER AREA BNE DDXT ;IF SAY NO THEN DON'T DO DUP LDA #0 STA WARMST ;TELL CART NO GOOD USER MEMORY STA ,MEMFLG ;TELL LOADER NO GOOD MEM.SAV CPTR1 RTS ; DDXT PLA ;POP RETURN ADDRESS PLA JMP MENUSL ;GOTO MENU, DON'T DO DUP ; ; ; DRVSTAT - SUBROUTINE TO DO STATUS ON DISK DRIVE SPECIFIED ; -BY THE NUMBER IN REG. A. ; RETURNS - CARRY SET = DEVICE HAS 256 BYTE SECTORS ; CARRY CLR = DEVICE HAS 128 BYTE SECTORS ; DRVSTAT STA DUNIT ;STORE UNIT NUMBER IN DCB LDA #STAREQ ;STORE STATUS COMMAND IN DCB . STA DCOMND LDA #2 ;SET RETRY COUNT STA RCNT DOSTAT JSR DKHND ;DO STATUS WITH OS HANDLER BPL CHKTYP ;IF GOOD RETURN, DETERMINE TYPE ; DEC RCNT ;ELSE SEE IF ANOTHER RET/RY BPL DOSTAT ;YES, DO AGAIN JMP CIOER1 ;ELSE ERROR EXIT ; CHKTYP CLC ;ASSUME 128 BYTE DEVICE LDA DVSTAT ;GET COMMAND STATUS BYTE AND #$20 ;MASK FOR DRIVE TYPE BIT- D5 0 BEQ RETSTAT ;128 IF = 0 SEC ;256 IF = 1 RETSTAT RTS ; ; SUBROUTINE - SETBUFL ; ; DETERMINE IF THE CURRENT SECTOR IS A BOOT SECTOR. IF IS USE 128 AS ; SECTOR SIZE, ELSE USE DEVICE SECTOR SIZE STORED IN1 SECSIZ. ; SETBUFL LDX #$80 ;ASSUME IS BOOT SECTOR LDY #0 ;BUFL IS LSB,MSB ORDER ; LDA DSHI ;TEST IF SECTOR # IS LES THAN 4-BOOT BNE LARGER ;IF HI BYTE NOT ZERO THEN USE DEVICE SECTOR SIZE 2 LDA DSLO ;ELSE TEST LOW BYTE FOR LESS THAN 4 CMP #4 ; BCC SETSIZ ;IF LESS THEN USE BOOT SIZE-128 ; LARGER LDX SECSIZ ;ELSE USE DEVICE SECTOR SIZE LDY SECSIZ+1 ; SETSIZ STX B3UFL ;SAVE DATA MOVE LENGTH STY BUFL+1 RTS ; **** DUPLICATE FILE COMMAND ****^ H ; ; ; DUPLICATE FILE FROM ONE DISK TO ANOTHER ;USING ONE DRIVE. FILENAME FOR DUPLICATE FILE IS SAME AS ;SOURCE NAME. USER CAN ENTER ONLY4 THE SOURCE FILE SPECIFICATION. ;USER HAS OPTION OF USING PROGRAM AREA FOR COPY OR A 250 BYTE ;DATA BUFFER TO GET PROGRAM AREA USER MUST RESPOND WITH ;'Y' AS 1ST CHAR OR THEY WILL GET THE DATA BUFFER. WILL DUPLICATE ;FILE OF ANY SIZE. IF ERROR, PRINTS M5SG, CLOSES FILE(S) OPEN AND ;RETURNS TO MENU. TO PREVENT POSSIBLE DAMAGE TO DESTINATION ;DISK, FILE IS OPENED AND CLOSED FOR EACH WRITE. ;MAKES BUFFER LENGTH AN EVEN MULTIPLE OF 125. THIS PREVENTS FRAGMENTATION ;OF THE FILE DUE TO THE APPEND OPEN FUNC6TION. 125 IS USED BECAUSE IT IS THE ;SIZE OF DATA PORTION IN A SECTOR. IF THIS CHANGES THE VALUE IN THE PGM ;MUST BE CHANGED. ; KEITH BALL 5/7/80 ; DPFM .BYTE 'NAME OF FILE TO MOVE?',CR ; DUPFIL .WORD DPFM ;DUPLICATE FILE PROMPT 7 JSR GETIC1 ;GET FILENAME TO DUPLICATE ON SAME DRIVE JSR PERX ;DON'T COME BACK IF PARAMETER ERRORS LDA PAR CMP #'D ;DUPLICATE FILE ONLY FOR DISK DEVICE BEQ ISDISK JMP OD8MS ;IF NOT -- SAY CANNOT DO & EXIT ; ISDISK JSR USEPGM ;ASK USER IF TO USE PROGRAM AREA OR BUFFER ; ; HAVE USER INSERT SOURCE FILE AND HIT WHEN DONE ; LDX #ISDH ;ARG: LINE TO BE DISPLAYED ADDR LDA #ISDL 9 ;IN REG. A & X JSR DSPLIN ;PRINT INSERT SOURCE MSG JSR GETLIN ;GOTO SCREEN & WAIT FOR JSR PERX ;GOTO MENU IF BREAK KEY HIT ; JSR LOOKWC ;SEE IF FILE SPEC. USES WILDCARDS :BNE NOWC ;BRANCH IF NO WILD CARDS USED - USE OLD ROUTINE LDA #$40 ;SET 'DUPLICATE WILDCARD' MODE JMP WCINIT ;OPEN WILDCARD DIRECTORY FILE, ETC. ; NOWC = * ; ; MAKE SURE DEST NOT DOS.SYS ; ; LDX #0 ;ENTRY-INDEX TO FIRST CHAR OF FILE NAME JSR TSTDOS ;WON'T RETURN IF IS DOS.SYS ; ; OPEN SOURCE FILE - ADDR OF FILENAME STRING IN PARAM LIST IS ; ALREADY ASSIGNED TO IOCBB # 2 ; WCDUPS LDX #$10 ;USE IOCB #2< LDA #OPEN ;OPEN COMMAND STA ICCOM,X LDA #4 ;READ ONLY STA ICAX1,X JSR CIOCL ;CALL CIO - IF ERR PRNT MSG,CLOSE, GOTO MENU ; ; EOFFLG - SOURCE FILE EOF FLAG FTRF - FLAG TO SH=OW IF 1ST TIME SOURCE ; FILE WAS READ ; LDA #0 STA EOFFLG ;CLEAR EOF FLAG STA FTRF ;CLEAR MEANS FIRST TIME ; ; DO UNTIL (SOURCE EOF FLAG(EOFFLG) IS SET) ; SET UP IOCB#2 TO DO GET CHAR. ZP LOC BUFADR HAS B>UFFER ADDRESS ; BUFLEN HAS BUFFER LENGTH ; DODUP LDX #$10 ;USE IOCB #2 LDA BUFADR ;IN LSB,MSB ORDER STA ICBAL,X ;SET BUFFER ^AADDR IN IOCB #2 LDA BUFADR+1 STA ICBAH,X LDA ? BUFLEN ;IN LSB,MSB ORDER STA ICBLL,X ;STORE BUFFER LENGTH LDA BUFLEN+1 ;IN IOCBB #2 STA ICBLH,X LDA #GETCHR ;COMMAND TO GET CHAR - IGNORE EOL'S (9B) STA ICCOM,X JSR @CIO ;CALL CIO ; ; CHECK FOR ENDFILE. IF YES, THEN SET FLAG. CHECK FOR ERROR. IF ERR ; THEN PRINT MSG, CLOSE FILE, AND RETURN TO MENU. ; BPL INSDES ;IF GOOD READ WRITE BUFFER CPY #EOF ;WAS IT EOF? BEQ ASETFLG ;YES, THEN SET FLAG JMP CIOER1 ;WAS ERR - PRINT MSG,CLOSE,GOTO MENU SETFLG DEC EOFFLG ;SET ENDFILE FLAG ; ; WHEN GOOD READ OR EOF GET HERE. ASK USER TO INSERT DESTINATION ; DISK AND ATTEMPT TO WRITE TO DESTINATION FIBLE. ; INSDES LDX #IDDH ;ARG: ADDRESS OF LINE TO BE PRINTED LDA #IDDL ;IN REGS A AND X JSR DSPLIN ;SAY TO SWAP DISKS JSR GETLIN ;WAIT TIL USER HITS BIT PER ;WAS BREAK KEYC HIT? BPL DODEST ;NO, TRY WRITE JMP CLSSRC ;YES, CLOSE & GOTO MENU ; ; CHECK IF FIRST TIME SOURCE WAS READ. IF YES, THEN OPEN FOR OUTPUT ; ONLY. OTHERWISE, OPEN FOR OUTPUT APPEND. ; DODEST LDX #$20 ;USE IOCB D#3 FOR DESTINATION LDY #9 ;ASSUME APPEND LDA FTRF ;IS FLAG CLEAR? BNE OPNDES ;NO,NOT FIRST TIME - OPEN APPEND LDY #8 ;YES, THEN OPEN OUT ONLY INC FTRF ;SET TO SHEOW NOT FIRST TIME NEXT TIME ; OPNDES TYA ;GET OPEN TYPE CODE STA ICAX1,X ;SET AUX1 BYTE LDA #OPEN ;OPEN COMMAND STA ICCOM,X ; ; THE FILENAME IS THE FIRST FILE IN THE PARAMETER LIST-PAR. ; F LDA #PARL ;SET BUFFER ADDRESS TO FILE SPEC TO BE OPENED LDY #PARH BIT WCFLAG ;IF WILDCARD USE WILDCARD BUFFER INSTEAD OF PAR BVC SKIPWC ; LDA #.LOW.WCBUF2 LDY #.HIGH.WCBUF2 ; SKGIPWC STA ICBAL,X TYA STA ICBAH,X JSR CIOCL ;CALL CIO, IF ERROR GOTO MENU ; ; CHECK IF SOURCE BUFFER LENGTH IS NOT EQUAL TO ZERO. IF NOT = ZERO ; THEN WRITE BUFFER TO THE DESTINATION FILE. ; LDY #$10H ;SOURCE IS AT IOCBB #2 LDX #$20 ;DEST IS AT IOCB #3 LDA #0 ;CHECK LENGTH LOW FOR ZERO CMP ICBLL,Y ;LOW=0 BNE DOWRIT ;NO THEN WRITE BUFFER CMP ICBLH,Y ;IS HI=0? I BEQ CLSDES ;YES, DON'T WRITE EMPTY BUFFER ; DOWRIT LDA #PUTCHR ;PUT CHAR COMMAND CODE STA ICCOM,X ;IGNORE EOLS (9B) LDA BUFADR ;GET BBUFFER ADDRESS STA ICBAL,X LDA BUFADR+1 J STA ICBAH,X LDA ICBLL,Y ;GET BUFFER LENGTH TO WRITE STA ICBLL,X ;FROM IOCB OF SOURCE FILE LDA ICBLH,Y ;SET BY GET TO ACTUAL BYTE STA ICBLH,X ;COUNT READ INTO BUFFER JSR CIOKCL ;DO WRITE - IF ERR GOTO MENU ; ; CLOSE DESTINATION FILE ; CLSDES LDA #CLOSE ;CLOSE COMMAND CODE STA ICCOM,X ;CALL CIO - IF ERROR GOTO JSR CIOCL ;MENU AFTER PRINT MSG ; ; TEST ENDFILE FLAG. LIF IT IS SET THEN COMPLETED DUPLICATION. ; OTHERWISE, DO LOOP BODY AGAIN (READ THEN WRITE). ; LDA EOFFLG ;IS SOURCE AT ENDFILE? BNE CLSSRC ;YES, THEN DONE ; ; ASK USER TO INSERT SOURCE FOR NEXT READ & THEN RMEPEAT LOOP ; LDX #ISDH ;ARGS: ADDRESS OF LINE TO PRINT IN LDA #ISDL ;REGS A AND X JSR DSPLIN ;SAY TO INSERT SOURCE JSR GETLIN ;WAIT TIL USER HITS BIT PER ;WAS BRENAK KEY HIT? BMI CLSSRC ;YES, CLOSE & GOTO MENU JMP DODUP ;REPEAT LOOP ; ; ******************END OF LOOP ; ; CLOSE SOURCE AND RETURN TO MENU ; CLSSRC LDX #$10 ;SOURCE AT IOCB #2 LDA #CLOOSE ;CLOSE COMMAND CODE STA ICCOM,X JSR CIO ;CALL CIO ; BIT WCFLAG ;TEST IF 'DUPLICATE WILDCARD' MODE BVC DUPFEX ;BRANCH IF NOT 'DUPLICATE WILDCARD' MODE LDX #ISDH ;INSEPRT SOURCE MESSAGE LDA #ISDL JSR DSPLIN ;NEEDED TO GET NEXT WILDCARD DIRECTORY ENTRY JSR GETLIN ;WAIT FOR CR JSR PERX ;IF BREAK-KEY ABORT - EXIT TO MENU JMP WCOPYL ;JUMP TO WILQDCARD LOOP DUPFEX = * ; JMP MENUSL ;GO TO THE MENU .PAGE ; **** ASK IF OK TO USE PROGRAM AREA ROUTINE ****^ H ; ; ;ASK USER IF CAN USE PROGRAM AREA. IF SAY YES ('Y') THEN ;ASSIGN BUFFER ADDRESS AS ALL AVAILABLE MREMORY. OTHERWISE, USE ;DBUF (250 BYTES) AS THE BUFFER. ASSIGNS BUFFER LENGTH. ; ;NO PARAMETERS ;RETURNS: BUFADR-BUFFER ADDRESS ; : BUFLEN-BUFFER LENGTH ; USEPGM LDA WARMST ;CHECK IF PGM AREA ALREADY BEQ USEDB4 ;USED-YES, SUSE IT AGAIN LDA #OKL ;ARGS: IN A AND X ADDR LDX #OKH ;OF LINE TO DISPLAY JSR DSPLIN ;ASK TO USE PGM AREA LDA #CMSIL ;SAY A Y RESPONSE WILL LDX #CMSIH ;INVALIDATE MEM.SATV JSR DSPLIN ;PRINT CAUTION JSR CHRGET ;GET 1ST CHAR OF CMP #'Y ;USERS RESPONSE BNE USEBUF ;NO THEN USE DBUFF ; ;USE ALL MEMORY AVAILABLE-PROGRAM AREA ;MEMLO,MEMTOP,BUFADR,BUFLEN ARE IN ULSB,MSB FORM ; USEDB4 LDA #0 ;CLEAR WARMSTART FLAG STA WARMST ;TO SHOW PGM AREA USED STA MEMFLG ;SHOW NO USER AREA GOOD-MEM.SAV ALSO LDA #NMDUPL ;USE ALL AVAILABLE STA BUFADR ;MVEMORY-FROM END OF DUP TO MEMTOP LDA #NMDUPH ;BUFADR HAS BUFFER STA BUFADR+1 ;ADDRESS LDA MEMTOP ;GET LENGTH OF SEC ;PGM AREA SBC #NMDUPL STA BUFLEN ;LSB,MSB WORDER LDA MEMTOP+1 SBC #NMDUPH STA BUFLEN+1 ; ; FIND THE GREATEST MULTIPLE OF 125 LESS THAN THE PROGRAM AREA ; THEN SET BUFFER LENGTH TO IT. THIS PREVENTS FRAGMENTATION TO FILE ; WHEN APPEND IS UXSED IN DUPFIL. ; LDA #0 ;INITIALIZE MULTIPLE OF 125 (MLT125) TO ZERO STA MLT125 STA MLT125+1 ; ; DO UNTIL (MLT125 > BUFLEN) ; FINDGM LDA #125 ;INC THE MULTIPLE OF 125 BY 125 CLC Y ;TO GET THE NEXT HIGHER MULTIPLE ADC MLT125 STA MLT125 LDA #0 ADC MLT125+1 ;MLT125 IS IN LSB,MSB ORDER STA MLT125+1 ; ; TEST FOR MLT125 > BUFLEN - LOOP TEST ; LDA ZBUFLEN+1 ;IS MSB OF MLT125 > MSB OF BUFLEN? CMP MLT125+1 BCC GETMLT ;YES, THEN END LOOP BNE FINDGM ;IF MLT LSB BUFLEN? BCS FINDGM ;NO, REPEAT LOOP ; ;ELSE END LOOP. ; END OF LOOP*********************** ; ; CHECK IF MULTIPLE = TO 125. IF IS, THEN LEAVE BUFLEN AS IS. IF ; ISN'T \THEN SET BUFLEN TO THAT NULTIPLE OF 125 MINUS 125. ; GETMLT LDA MLT125+1 ;IS MSB NOT = ZERO? BNE REPLAC ;YES, VALUE IS > 125 LDA #125 ;IS LSB > 125? CMP MLT125 ; BCC REPLAC ;YES, R]EPLACE BUFLEN WITH MLT125 RTS ;ELSE LEAVE BUFLEN AS IS ; ; REPLAC LDA MLT125 ;SUBTRACT 125 FROM MLT125 TO GET SEC ;GREATEST MULTIPLE LESS THAN OR EQUAL SBC #125 ^ ;TO THE PROGRAM AREA. STA BUFLEN ;USE IT AS THE BUFFER LENGTH. LDA MLT125+1 SBC #0 STA BUFLEN+1 RTS ;RETURN ; ;USE BUFFER DBUF (250 BYTES) INSTEAD OF PROGRAM AREA ; USEBUF _ LDA #DBUFL ;USE DBUF AS STA BUFADR ;BUFFER ADDRESS LDA #DBUFH ;IN LSB,MSB ORDER STA BUFADR+1 ; LDA #EDBLL ;STORE DATA STA BUFLEN ;BUFFER LENGTH LDA #EDBLH` ;=TO 256(100HEX) STA BUFLEN+1 ;IN LSB,MSB ORDER RTS ;RETURN .PAGE ; **** CHECK FILENAME FOR WILDCARD CHARACTERS ****^ H ; ; ; CHECKS THE STRING AT PAR,X FOR WILD CARD CHARACTERS (* OR ?). IaF ; THEY ARE FOUND THE ROUTINE SETS THE EQUAL FLAG. IF A IS FOUND ; RETURNS TO THE CALLING ROUTINE WITH THE EQUAL FLAG RESET. ; LOOKWC LDA PAR,X INX CMP #'* BEQ LOOKW2 CMP #'? BEbQ LOOKW2 CMP #CR BEQ LOOKW1 CMP #', ;TERMINATE WITH CR OR COMMA BNE LOOKWC ; LOOKW1 INX LOOKW2 RTS .PAGE ; **** TEST FILE SPEC FOR DOS.SYS ****^ H ; ; ; SUBROUTINE - TSTDOS ; ; c CHECKS A FILE SPEC IN THE STORAGE LOC FOR DOS.SYS. USED TO ; PREVENT COPYING TO A FILE NAMED DOS.SYS. IF DOS.SYS IS OPENED ; OUTPUT FMS WILL WRITE A COPY OF DOS OUT TO THE FILE. ; ; ENTRY - REG X HAS INDEX INTO PAR TO FIRST CHAdR OF FILE SPEC ; ASSUMES COMPLETE FILE SPEC. ; EXIT - WILL NOT RETURN IF FILE NAME = DOS.SYS, BUT GOES TO MENU. ; ; FIND END OF DEVICE ID - COLON ; TSTDOS INX ;NEVER IS FIRST CHAR LDA PAR,X ;GEeT 2ND CHAR CMP #': ;IS IT A COLON? BEQ GOTCOL ;YES, THEN NAME STARTS AT CHAR 3 INX ;ELSE NAME STARTS AT CHAR 4 GOTCOL INX ;POINT AT FIRST CHAR OF NAME ; ; COMPARE FILE NAME fIN PAR WITH DOS.SYS ; LDY #0 ;INDEX INTO DOS.SYS FILE SPEC ; NXTCHAR LDA DS+3,Y ;GET NEXT DOS.SYS CHAR CMP PAR,X ;TEST IF FILE NAME IS SAME BNE NOTSAM ;NO, THEN RETURN INY g ; INX ;ELSE TRY NEXT CHAR CPY #7 ;ARE THERE MORE CHARS TO TRY? BNE NXTCHAR ;YES, DO AGAIN ; ; FILE NAME EQUALS DOS.SYS - ERROR EXIT ; LDA #DCDSL ;PRINT MSG - DEST CAN'T BhE DOS.SYS LDX #DCDSH JSR DSPLIN JMP MENUSL ;GOTO MENU ; ; NOT EQUAL TO DOS.SYS - RETURN TO CALLER ; NOTSAM RTS ; DCDS .BYTE 'DESTINATION CANT BE DOS.SYS',CR HILO DCDS .PAGE ; **** iSAVE FILE ROUTINE ****^ H ; ; SAVFIL .WORD SFMG LDA #0 STA INITQ+1 STA RUNQ+1 JSR GETIC1 LDA OPT PHA LDX PTR ;PUT EOL ON FILENAME LDA #CR STjA PAR-1,X JSR GETNO ;GET HEX PARAMETER STA LDST STX LDST+1 CPX #NDSH BCS DSLMFG ;BRANCH IF NOT SAVING DUP AREA DEC WDR1+1 DSLMFG JSR GETNO ;END ADDRESS k STA LDND STX LDND+1 SEC SBC LDST STA WDRL+1 TXA SBC LDST+1 BPL ADDOK ;BRANCH IF ENDING ADDRESS GREATER THAN STARTING JMP MENUSL ;ELSE BACK TO MENU ADDlOK STA WDRH+1 CPY #CR BEQ NRUNAD ;BRANCH IF NO MORE PARAMS JSR GETNO ;GET A RUN ADDRESS IF ANY STA INITAD STX INITAD+1 ORA INITAD+1 BEQ NINTAD ;BRANCHm IF NO INIT ADDRESS GIVEN DEC INITQ+1 ;SET FLAG NINTAD CPY #CR BEQ NRUNAD ;BRANCH IF NO RUN ADDRESS GIVEN JSR GETNO ;GET RUN ADDRESS JSR PERX ;CHECK FOR ERRORS STA RUNAD n STX RUNAD+1 ORA RUNAD+1 BEQ NRUNAD ;BRANCH IF NO RUN ADDRESS DEC RUNQ+1 ;SET FLAG NRUNAD LDA #0 STA OPT PLA ;OPTION CHAR FROM FILENAME CMP #'A o ;IF APPEND BNE *+5 DEC OPT ;SET OT=$FF ; OPEN THE FILE LDX #$10 LDA #OPEN STA ICCOM,X BIT OPT ;IF APPEND BMI *+6 LDA #8 BNE *+p4 LDA #9 STA ICAX1,X JSR CIOCL ; WRITE SAVE FILE HEADER LDA #PUTCHR STA ICCOM,X LDA #SAVHL STA ICBAL,X LDA #SAVHH STA ICBAH,X LDA #6 q STA ICBLL,X LDA #0 STA ICBLH,X BIT OPT BPL WHEAD ;BRANCH IF NOT APPEND LDA #4 STA ICBLL,X LDA #LDSTL STA ICBAL,X LDA #LDSTH r STA ICBAH,X WHEAD JSR CIOCL ; WRITE DATA RECORD WDR LDX #$10 WDRL LDA #0 ;THIS IMMEDIATE VALUE MODIFIED STA ICBLL,X WDRH LDA #0 ;THIS IMMEDIATE VALUE MODIFIED STA ICBLH,X s INC ICBLL,X BNE *+5 INC ICBLH,X LDA LDST STA ICBAL,X LDA LDST+1 STA ICBAH,X WEX JMP WDR1 SFMG .BYTE 'SAVE-GIVE FILE,START,END' .BYTE $5B,',INIT,RUN',$5Dt,CR .PAGE ; **** MISC. SUBROUTINES ****^ H ; ; GETLIN LDA #CR LDX #79 STA LINE,X DEX BPL *-4 LDA #0 STA PTR STA IPTR STA PER JSR CIOuGET JSR SCROL RTS ; ; ; ; CIOGET - GET LINE OF INPUT FROM SCREEN EDITOR ; CIOGET LDA #GETREC STA ICCOM ;SCREEN EDIT IOCB LDA #LBUFL STA ICBAL LDA #LBUFH STA ICBAH v LDA #80 STA ICBLL LDA #0 STA ICBLH LDX #0 JSR CIO ;READ RECORD FROM SCREEN EDITOR CPY #$80 ;CHECK FOR BREAK ABORT STATUS BNE *+5 DEC w PER ;PARAM ERROR FLAG IS SET IF SO RTS ; ; ; CHRGET - GET 1 CHAR FROM EDITOR IN A. ; CHRGET LDA #0 STA PER CHRG1 JSR CIOGET ;GET A LINE FROM E: LDA ICBLL ;SAVE CHAR COUNT STA RCNT x JSR SCROL LDA PER BPL CHRG2 ;IF BREAK, CLOSE AND EXIT JSR CLOSX JMP MENUSL CHRG2 LDA RCNT ;EXPECT 1 OR 2 CHARACTERS CMP #3 BMI CHRG3 ;IF OK yLDA #OLL LDX #OLH JSR DSPLIN JMP CHRG1 ;TRY AGIN CHRG3 LDA LINE ;GET 1ST CHAR RTS .PAGE OL .BYTE 'PLEASE TYPE 1 LETTER',CR HILO OL ; ; PERX - EXIT IF PARAMETER ERzRORS ; PERX BIT PER BMI PERX1 RTS PERX1 PLA PLA JMP MENUSL ; ; GETIC1 - READ LINE, GET FILENAME, POINT TO IT IN IOCB1 ; GETIC1 JSR GETLINE GETIC2 LDX #$10 JSR PIOCB JMP G{ETFIL ; ; GETNAME LDA #8 ;ENTRY TO GETFIL USED BY RENAME STA CTR ;WHICH DOES NOT HAVE A DEVICE ID LDY PTR ;FOR THE SECOND FILE SPEC LDX IPTR JMP CFTE ; ; SUBROUTINE - GETFIL|^ H ; REMOVES ONE FILE SPECIFICATION FROM THE INPUT LINE. WILL SET UP ; THE SPEC FOR DEFAULTS FOR INCOMPLETE DRIVE ID. DEFAULT DRIVE # IS ; 1. ; ; ;GET FILESPEC FROM INPUT LINE GETFIL LDY PTR LDX IPTR LDA }#11 STA CTR ;AVOID GETTING JUNK ON VERY SHORT PARAMS LDA LINE,X CMP #', BEQ ADDC CMP #CR BEQ ADDC LDA LINE+1,X CMP #', BEQ GT1 CMP #C~R BEQ GT1 LDA #': ;LOOK FOR : IN FILESPEC CMP LINE+2,X ;SEE IF HAVE COMPLETE FILESPEC ALREADY BEQ CFTE CMP LINE+1,X BNE GT1 DEC CTR LDA LINE,X  CMP #'A BPL CFTE ;HAVE X:FILE, COMPLETE FILESPEC ;IF FALLS THRU, IS UNIT:FILE; ADD D GT2 LDA #'D STA PAR,Y INY BPL CFTE GT1 DEC CTR DEC CTR CMP LINE,X ;AN UNLIKELY CASE (:FILE) BEQ GT2 ;TREAT :FILE AS U:FILE DEC CTR ADDC LDA #'D STA PAR,Y INY LDA #': STA PAR,Y INY CFTE LDA #0 STA OPT CFTE1 LDA LINE,X STA PAR,Y INX INY CMP #CR ;LOOK FOR TERMINATOR BEQ EOC CMP #', BEQ EOC CMP #'/ BEQ POPT CMP #'. ;LOOK FOR START OF .EXT BNE CFTE2 LDA #4 ;FOUND, 4 MORE CHARS MAX STA CTR CFTE2 DEC CTR BPL CFTE1 ;GETS HERE IF TOO MANY CHARS IN FILENAME LDA #NTLL LDX #NTLH JSR DSPLIN ;NAME TOO LONG DEC PER ;SET PARAMETER ERROR FLAG STE LDA LINE,X ;SKIP TO END INX CMP #', BEQ EOC CMP #CR BNE STE EOC STX IPTR STY PTR RTS POPT LDA LINE,X STA OPT INX LDA LINE,X STA PAR-1,Y ;CHANGE STORED TERMINATOR TO , OR CR I HOPE INX BPL EOC NTL .BYTE 'NAME TOO LONG',CR HILO NTL ; ; DSPMSG - DISPLAY N BYTES ; BUFFER POINTER AND LENGTH ARE ALREADY IN IOCB0 ; DSPMSG LDA #PUTCHR STA ICCOM LDX #0 ; CIO1 JSR CIO ;CALL CIO AND GO TO MENUSL CPY #$80 ;IF BREAK KEY ABORT BNE  *+5 JMP MENUSL RTS ; ; DSPLIN - DISPLAY ONE LINE OF TEXT ; A=LO,X=HI ADDRESS DSPLIN JSR PRNTMSG ;USE RESIDENT DUP SUBROUTINE JMP SCROL ;SCROLL SCREEN BELOW MENU & RETURN ; ; ; SCROL - DO SCROLLING OF AREA BELOW MENU ; SCROL LDA #0 TAX STA ICBLH,X LDA #10 STA ICBLL,X LDA #ZAPH STA ICBAH,X LDA #ZAPL STA ICBAL,X JMP DSPMSG .PAGE ZAP  .BYTE CUP,CUP,CUP,CUP,CUP .BYTE DLL,CDN,CDN,CDN,CDN HILO ZAP ; ; PIOCB - POINT IOCB AT PAR(PTR) ; PIOCB LDA #PARL CLC ADC PTR STA ICBAL,X LDA #PARH ADC #0 STA  ICBAH,X RTS ; ; CIOCL - CALL CIO AND PROCESS ANY ERRORS ; CIOCL JSR CIO ;CALL CIO TYA BMI *+3 RTS ;OK, RETURN CIOER1 TYA ;ERROR STATUS CIOER SEC SBC #100  ;ERROR NUMS ALWAYS ARE 1XX DEC LDX #'0-1 ;CONVERT TENS CTNS INX SEC SBC #10 BPL CTNS ;THE EASY (SLOW) WAY CLC ADC #10+'0 ;CONVERT STA EUN STX ETN LDX #CIEH LDA #CIEL CIEX JSR DSPLIN JSR CLOSX ;CLOSE IOCBS 10,20 JMP MENUSL CIE .BYTE 'ERROR- 1' ETN .BYTE 0 EUN .BYTE 0 .BYTE CR HILO CIE ; ; ; GETNO - GET HEX NUMERIC PARAMETER FROM LINE(IPTR). ; RETURN A=LO, X=HI. PER SET MINUS IF ERROR. ; INC IPTR PAST PARAM. ; GETNO LDA #4 ;MAX NO DIGITS STA CTR LDA #0 STA T1 STA T1+1 ;INIT TEMP TO BUILD NUMBER IN GHB LDX IPTR LDA LINE,X ;GET CHAR INC IPTR CMP #CR ;SEE IF TRMINATOR BEQ GND CMP #', BEQ GND JSR HEXCON ;CONVERT ASCII TO NIBBLE BMI ERRX ;IF ERROR LDY #3 ;SHIFT T1,T1+1 BY 4 SHT1 CLC ROL T1+1 ROL T1 DEY BPL SHT1 ORA T1+1 ;OR IN NEW NIBBLE STA T1+1 DEC CTR ;COUNT DIGIT BPL GHB ;LOOP UNLESS TOO MANY DIGITS LDA #TMDL LDX #TMDH ERRX1 JSR DSPLIN DEC PER RTS GND TAY LDA T1+1 LDX T1  RTS ERRX LDA #IHPL ;INVALID HEX PARAM LDX #IHPH BNE ERRX1 TMD .BYTE 'TOO MANY DIGITS',CR HILO TMD IHP .BYTE 'INVALID HEXADECIMAL PARAMETER',CR HILO IHP ; ; ; HEXCON - CONVERT ASCII CHAR IN A TO HEX NIBBLE IN A. RETURN ; MINUS CONDITION, A=FF IF ERROR. ; HEXCON SEC SBC #'0 BMI ERRX2 ;ASCII BELOW '0' CMP #10 BMI OKX ;0-9 CONVERTED SO EXIT SEC  SBC #'A-'0-10 CMP #10 ;CONVERTED VALUE MUST BE 10 OR MORE BMI ERRX2 ;BETWEEN '9' AND 'A' CMP #$10 BMI OKX ;A-F CONVERTED ERRX2 LDA #$FF OKX CMP #0 ;SET STATUS BY VALUE IN A RTS ; ; GETDN - GET A DEVICE NUMBER FROM LINE(IPTR) ; RETURN IT IN A ; GETDN BIT PER ;SEE IF PARAM ERROR ALREADY BMI GDR ;IF SO DONT BOTHER LDX IPTR GETD LDA LINE,X  INX CMP #'D ;IF DN BEQ GETD ;GO GET DIGIT SEC SBC #'0 ;CONVERT DIGIT BEQ BDS ;CANT BE ZERO BMI BDS ;IF NOT DIGIT CMP #DRTST ;TEST FOR BEYOND DRIVE MAX BPL BDS ;TOO LARGE PHA GD1 LDA LINE,X INX CMP #', BEQ GDX ;IF TERMINATOR CMP #CR BNE GD1 ;KEEP LOOKING GDX STX IPTR  ;ADVANCE POINTER PLA GDR RTS BDS DEC PER LDA #NDSL ;NEED DEVICE SPEC MSG LDX #NDSH JMP DSPLIN NDS .BYTE 'NEED D1 THRU D8',CR NMDUP .BYTE 0 LEN = NMDUP-EDN HILO  LEN MLEN = NMDUP-NDOS HILO MLEN HILO NDS HILO NMDUP .END n; .TITLE 'FMS - 128/256 BYTE SECTOR' .TITLE 'FMS FOR DOS 2.0D MODIFIED APRIL 25,81 FOR CORVUS BY MIKE L.' LIST X ; PROGRAMMER PAUL LAUGHTON ; 4.9D 05-FEBRUARY-81 ; SPECIAL VERSION FOR 815 2.0D ; MIKE L. MODIFIED FOR CORVUS APRIL 25,1981 ; ;********************************************************************* ; (C) 1978 SHEPARDSON MICROSYSTEMS, INC ;********************************************************************* ; ;********************************************************************* ; FILENAME: MIKEL.CFMSSRC ON TANDEM ;********************************************************************* ; ; FMSORG = $700 FMSZPG = $43 IOCBORG = $340 LMASK = 03 ; LINK MASK DCBORG = $300 ;DHADR = $E453 ;MOVED DHADR EQUATE TO CVECT1 EOL = $9B DEVTAB = $31A ZICB = $20 LMADR = $2E7 DUPINIT = $1540 ;INIT ADDRESS FOR DUP STAK = $102 ; STACK LOC FOR PUT BYTE OSBTM = $DF ; HI BYTE OF ADDRESS LESS THAN OS SPACE, IN PUT DSKTIM = $246 ; ADDR OF OS WORST CASE DISK TIME OUT TIMOUT = 15 ; TIME OUT VALUE OF 15 SECONDS .PAGE 'IOCB'  *= IOCBORG ; ; IOCB - I/O CONTROL BLOCK ; THERE ARE 8 I/O CONTROL BLOCKS ; 1 IOCB IS REQUIRED FOR EACH ; CURRENTLY OPEN DEVICE OF FILE. ; IOCB ICHID *=*+1 ; DEVICE HANDLER ID ICDNO *=*+1 ; DEVICE NUMBER ICCOM *=*+1 ; I/O COMMAND ICSTA *=*+1 ; I/O STATUS ICBAL *=*+1 ICBAH *=*+1 ; BUFFER ADR (H,L) ICPUT *=*+2 ; PUT CHAR DH ADR ICBLL *=*+1 ICBLH *=*+1 ; BUFFER LENGTH (H,L) ICAUX1 *=*+1 ; AUXILLIARY 1 ICAUX2 *=*+1 ; AUXILLIARY 2 ICAUX3 *=*+1 ; AUXILLARY 3 ICAUX4 *=*+1 ; AUXILLARY 4 ICAUX5 *=*+1 ICAUX6 *=*+1 ICLEN = *-IOCB ; *=*+ICLEN*7 ; SPACE FOR 7 MORE IOCBS ; ; ICCOM VALUE EQUATES ; ICOIN = $01 ; OPEN INPUT ICOOUT = $02 ; OPEN OUTPUT ICOIO =  $03 ; OPEN UN/OUT ICGBR = $04 ; GET BINARY RECORD ICGTR = $05 ; GET TEXT RECORDS ICGBC = $06 ; GET BINARY CHAR ICGTC = $07 ; GET TEXT CHAR ICPBR = $08  ; PUT BINARY RECORD ICPTR = $09 ; PUT TEXT RECORD ICPBC = $0A ; PUT BINARY CHAR ICPTC = $0B ; PUT TEXT CHAR ICCLOSE = $0C ; CLOSE FILE ICSTAT = $0D ;GET STATUS ICDDC = $0E ; DEVICE DEPENDENT ICMAX = $0E ; MAX VALUE ICFREE = $FF ; IOCB FREE INDICATOR ; ; ICSTA VALUE EQUATES ; ICSOK = $01 ; STATUS GOOD, NO ERRORS ICSTR =  $02 ; TRUNCATED RECORD ICSEOF = $03 ; END OF FILE ICSBRK = $80 ; BREAK KEY ABORT ICSDNR = $81 ; DEVICE NOT READY ICSNED = $82 ; NON-EXISTENT DEVICE ICSDER = $83 ; DATA ERROR ICSIVC = $84 ; INVALID COMMAND ICSNOP = $85 ; DEVICE/FILE NOT OPEN ICSIVN = $86 ; INVALID IOCB NUMBER ICSWPE = $87 ; WRITE PROTECTION ; ; ZERO PAGE IOCB LABELS ; ICDNOZ = ICDNO-IOCB+ZICB ; DRIVE # ICBLLZ = ICBLL-IOCB+ZICB ; BUF LENGTH ICBLHZ = ICBLH-IOCB+ZICB ; ICBALZ = ICBAL-IOCB+ZICB ; BUF ADR ICBAHZ = ICBAH-IOCB+ZICB ICCOMZ = ICCOM-IOCB+ZICB ICPUTZ = ICPUT-IOCB+ZICB ; PUT ROUTINE ADDRESS .PAGE 'DCB' *= DCBORG ; ; DCB - DATA CONTROL BLOCK ; THE DCB IS A IOCB LIKE CONTROL BLOCK USED ; TO INTERFACE THE DISK FILE MANAGEMENT SYSTEM ; TO THE DISK HANDLER ; DCB DCBSBI *=*+1 ; *SERIAL BUS ID DCBDRV *=*+1 ; -DISK DRIVE NUMBER DCBCMD *=*+1 ; -COMMAND DCBSTA *=*+1 ; * U/O STATUS DCBBUF *=*+2 ; -I/O BUFFER ADR (H,L) DCBTO *=*+2 ; *TIME OUT COUNT (H,L) (1/60 SEC) DCBCNT *=*+2 ; *U/O BYTE COUNT (H,L) DCBSEC *=*+2 ; I/O SECTOR NUMBER (H,L) ; ; DCBCMD VALUE EQUATES ; DCBCRS = $52 ; READ SECTOR DCBCWS = $57 ; WRITE SECTOR DCBCST = $53 ; STATUS REQUEST DCBCFD = $21 ; FORMAT DISKETTE ; ; DCBSTA VALUE EQUATES ; DCBSOK =  $01 ; STATUS NORMAL DCBDNR = $81 ; DEVICE NOT READY DCBCNR = $82 ; CONTROLLER NOT READY DCBDER = $83 ; DATA ERROR DCBIVC = $84 ; INVALID COMMAND DCBWPR = $87  ; WRITE PROTECT .PAGE 'ZERO.PAGE' *= FMSZPG ZBUFP *=*+2 ;BUFFER PTR ZDRVA *=*+2 ;ZERO .PAGE DRIVE PTR ZSBA *=*+2 ; ZERO .PAGE SECTOR BUFF PTR ERRNO *=*+1 ;ERROR NUMBER .PAGE 'BOOT RECORD' *= FMSORG ; ; THEFOLLOWING BYTES ARE STORED ON DISK ; SECTOR 0 THEY COMPRISE THE BOOT LOADER ; RECORD. ; BFLG .BYTE 0 ;BOOT FLAG (UNUSED,=0) BRCNT .BYTE 3 ; NO CONSECTUTIVE BOOT SECTORS TO READ BLDADR .WORD FMSORG ;BOOT LOAD ADR BINTADR .WORD DUPINIT ;INITILZATION ADR BCONT JMP XBCONT ;BOOT READ CONTINUE ENTRY POINT ; ; THE FOLLOWING BYTES ARE SET BY THE CONSOLE PROCESSOR. ; THEY ARE ACTED UPON DURING FMS INIT ONLY. ; THEY ARE PART OF THE BOOT RECORD, THUS DEFINING ; THE DEFAULT INITILIZATION PARMS. ; SABYTE .BYTE 3 ;MAX NUMBER CONCURRENT OPEN FILE DRVBYT .BYTE 01 ; DRIVE BITS SAFBSW .BYTE 0 ;STORAGE ALLOCATION DIRECTION SWITCH SASA .WORD ENDFMS ;STORAGE ALLOCATION START ADR ; ; THE FOLLOWING CODE READS THE FMS AND CONSOLE ; PROCESSOR (DOS) FROM THE DOS.SYS FILE ; DFSFLG .BYTE 0 ; DOS FLAG ; 00 - NO DOS FILE ; 01 - 128 BYTE SECTOR DISK ; 02 - 256 BYTE SECTOR DISK DFLINK .BYTE 0,0 ; DOS FILE START SECTOR NUMBER BLDISP .BYTE 125 ; DISPL TO SECTOR LINK DFLADR .WORD DFMSDH ; ADR START OF DOS.SYS FILE ; XBCONT LDY DFSFLG ; GET DOS FLAG BEQ BFAIL ; BR IF NO DOS.SYS FILE ; LDA DFLADR ; MOVE LOAD START ADR STA ZBUFP ; TO ZERO PAGE PTR STA DCBBUF ; AND TO DCB LDA DFLADR+1 STA ZBUFP+1 STA DCBBUF+1 ; ; LDA DFLINK+1  ;GET FIRST SECTOR NUMBER LDY DFLINK XBC1 CLC ;SET READ LDX DFSFLG ; LOAD DISK TYPE CODE JSR BSIO ;GO READ BOOT SECTOR BMI BFAIL ; LDY BLDISP  ;POINT TO LINK LDA (ZBUFP),Y ; GET LINK HI AND #LMASK ;MASK TO LINK BITS PHA ;SAVE INY ORA (ZBUFP),Y BEQ BGOOD LDA (ZBUFP),Y ; GET LINK LOW TAY ; TO Y JSR INCBA ;GO INCREMENT BUF ADR ; PLA ;RESTOR LINK HI JMP XBC1 ;GO READ NEXT SECTOR ; BFAIL LDA #$C0 ;SET FOR CARRY SET BNE XBRTN ;ANY P,Y = $80 ; BGOOD PLA ; SET FOR CARRY CLEAR ; ;AND A,Y = 0 XBRTN ASL A TAY RTS ;DONE BOOT READ ; INCBA CLC LDA ZBUFP ; INC BUFFER POINTER ADC BLDISP ;BY DATA LENGTH (125) STA DCBBUF STA ZBUFP LDA ZBUFP+1 ADC #0 STA DCBBUF+1 STA ZBUFP+1 RTS ; .PAGE  'SECTOR I/O' ; ; BSIO - DO SECTOR I/O ; BSIO = * ; STA DCBSEC+1 ; SET SECTOR (HI) STY DCBSEC ; SET SECTOR (LOW) ; BSIOR LDA #DCBCRS ; ASSUME READ SECTOR LDY  #$40 ; AND GET DATA BCC DSIO1 ; BR IF READ ; LDA #DCBCWS ; ELSE LOAD WRITE SECTOR LDY #$80 ; AND PUT DATA ; DSIO1 STA DCBCMD  ; SET COMMAND STY DCBSTA ; AND SIO CMD ; LDA #$31 ; DISK SERIAL BUS ID LDY #TIMOUT ; TIME OUT DEFAULT LOADED ; DSIO2 STA DCBSBI ; SET ID STY DCBTO ; SET TIME OUT ; LDA #3 ;SET RETRY COUNT STA RETRY ; LDA #0 ; ASSUME 128 BYTE LDY #$80 ; SECTOR DISK DEX ; IF X=1 IS 128 BYTE BEQ DSIO3 ; SO BR ; LDA #1 ; ELSE IS 256 LDY #0 ; DSIO3 STA DCBCNT+1 ; SET I/O BYTE COUNT  STY DCBCNT ; DSIO4 ; JSR $E459 ; CALL SERIAL I/O JSR CVECT2 ****** CORVUS ****** BPL DSIO5 ; IF GOOD I/O THEN RETURN ; DEC RETRY ; TEST IF ANOTHER RETRY AVAILABLE BMI DSIO5 ; NO, THEN RETURN WITH ERROR ; LDX #$40 ; DO RETRY - RESET TYPE ACTION LDA #DCBCRS ; ASSUME READ - CHK IF IS CMP DCBCMD ; IS COMMAND GET SECTOR? BEQ STRTYP ; YES, THEN STORE GETSECTOR IN DCB LDA #DCBCFD ; TEST IF FORMAT COMMAND CMP DCBCMD  ; IT ALSO RECEIVES DATA BEQ STRTYP ; YES, THEN SET AS GET DATA LDX #$80 ; ELSE STORE PUTSECTOR STRTYP STX DCBSTA ; JMP DSIO4 ; RETRY THE I/O ; DSIO5 LDX  CURFCB ; RELOAD CURRENT FCB LDA DCBSTA ; AND I/O STATUS, SET FLAGS RTS ; .PAGE 'FILE MANAGER ENTRY POINT' ; ; DFMSDH - DISK FILE MANAGEMENT DISK HANDLER ENTRY POINT ; DFMSDH .WORD DFMOPN-1 ; OPEN FILE .WORD DFMCLS-1 ; CLOSE FILE .WORD DFMGET-1 ; GET BYTE .WORD DFMPUT-1 ; PUT BYTE .WORD DFMSTA-1 ; STATUS .WORD DFMDDC-1 ; DEVICE DEPENDENT CMND .PAGE 'INITILIZATION' ; ; INITILIZATION CODE ; *= $7E0 ; GIVE ROOM FOR BOOT EXPANSION!!!!! DINIT = * ; ; SET UP DRIVE INFO ; DRVTBL - 8 BYTES - ONE FOR EACH POSSIBLE DRIVES ;  0 = NO DRIVE ; 1 = 128 BYTE SECTOR DRIVE ; 2 = 256 BYTE SECTOR DRIVE ; DBUFA(L,H) - 8 TWO BYTE ENTRIES ; THE DRIVE (VTOC) BUFFER ADR FOR A DRIVE ; LDA SASA ; MOVE START OF ALLOCATION STA ZBUFP ; AREA TO ZBUFP LDA SASA+1 STA ZBUFP+1 ; LDA DRVBYT ; TEMP 1 IS DRIVE STA TEMP1 ; EXIST BITS FROM BOOT ; LDX #7  ; TEMP2 IS ; DIA STX TEMP2 ; DRIVE NIMBER MINUS ONE ASL TEMP1 ; SHIFT DRIVE BIT TO CARRY BCS DIHAVE ; BR IF DRIVE EXISTS ; LDA #0 ; DRIVE DOES NOT EXITS  STA DRVTBL,X ; SET NO DRIVE STA DBUFAL,X ; AND NO BUFFER STA DBUFAH,X BEQ DIDDEC ; GO DEC DRIVE NO. ; DIHAVE LDY #DVDWRQ ; SET WRITE REQD OFF LDA #0  STA (ZBUFP),Y ; IN THE DRIVE BUFFER ; INX STX DCBDRV ; PUT DRIVE NO. INTO DCB LDA #DCBCST ; GET DRIVE STATUS STA DCBCMD JSR DHADR ; VIA OP SYS ; LDY  #2 ; ASSUME 256 BYTE DRIVE LDA $2EA ; GET STATUS BYTE AND #$20 ; AND TEST 256 BNE DI256 ; BR IF 256 DEY ; DI256 TYA LDX TEMP2 ; SET DRIVE TYPE INTO STA DRVTBL,X ; TABLE AT DRIVE DISPL LDA ZBUFP ; MOVE CURRENT ALOC STA DBUFAL,X ; ADR TO DBUFA LDA ZBUFP+1 ; AND INC ALOC STA DBUFAH,X ; BY 128 BYTES JSR DINCBP ; VIA DINCBP ; DEY ; IF DRIVE WAS A BEQ DIDDEC ; 128 BYTES THEN DONE ; JSR DINCBP ; ELSE INC PTR BY 128 ; DIDDEC DEX ; DEC DRIVE BPL DIA ; BR IF MORE TO TEST ; ; SET UP SECTOR ALLOCATION TABLE ; THE SECTOR ALLOCATION TABLE (SECTBL) HAS 16 ONE BYTE ; ENTRIES, ONE FOR EACH POSSIBLE 128 BYTE BUFFER SABYTE ; IN THE BOOT RECORD DETERMINES THE NUMBER OF ENTRIES TO ; ALLOCATE. NON-ALLOCATED BYTES ARE MINUS. ; ; SABUF(L,H) CONTAIN THE ADR OF THE SECTOR BUFFER ; LDY SABYTE ; GET AND SAVE COUNT LDX #0  ; SET CURRENT BUFFER NO. ; DINXTS LDA #0 ; ASSUME ALLOCATE DEY ; DEC COUNT OF ALLOCATED BPL DISETS ; IF PLUS STILL ALLOCATE TYA ; ELSE DE-ALLOCATE ; DISETS STA SECTBL,X ; SET ALLOCATE BYTE TYA ; IF NO ALLOCATED BMI DISNI ; THEN DON'T ALLOCATE BUFF ; LDA ZBUFP ; MOVE BUFFER ADDR STA SABUFL,X ; TO SECTOR BUF PTR LDA ZBUFP+1 STA SABUFH,X JSR DINCBP ; INC SECTOR ADDR ; DISNI INX ; INC BUFFER NO CPX #16 ; IF NOT ALL 16 BNE DINXTS ; DO AGAIN ; ;  SET LOW MEM ; LDA ZBUFP ; MOVE FINAL ADDR STA LMADR ; TO LOMEM PTR LDA ZBUFP+1 STA LMADR+1 ; JMP CLRFCB ; CONTINUE INIT ; ; DINCBP - INC ZBUFP BY 128 ; DINCBP CLC LDA ZBUFP ADC #128 STA ZBUFP LDA ZBUFP+1 ADC #0 STA ZBUFP+1 RTS ; ; CLEAR FCBS TO ZERO ; CLRFCB = * LDY #$7F ; 128 OF FCB  LDA #0 CFCBX STA FCB,Y ; TO BE CLEARED DEY BNE CFCBX ; .PAGE ; LDY #0 ADI1 LDA DEVTAB,Y ;FIND AN BEQ ADI2 ; UNUSED CMP #'D ; OR DISK BEQ ADI2 ; EMPTY INY INY INY CPY #30 BNE ADI1 BRK ; ELSE BREAK ; ADI2 LDA #'D ; SET DISK STA DEVTAB,Y LDA  #.LOW.DFMSDH ; SET FMS ADR STA DEVTAB+1,Y ; LDA #.HIGH.DFMSDH STA DEVTAB+2,Y ; RTS ; DONE INIT .PAGE 'OPEN' ; ; DFMOPN - FILE OPEN EXECUTION ENTRY POINT ; DFMOPN JSR SETUP ; DO FCB SET UP JSR FNDCODE ; GO DECODE FILE NAME LDA ICAUX1,X ; GET AUX1 (OPEN TYPE CODES) STA FCBOTC,X ; PUT INTO FCB AND #OPDIR ; IS THIS LIST DIRECTORY BEQ OPN1 ; BR IF NOT JMP LISTDIR ; GO TO DIR LIST CODE ; OPN1 JSR SFDIR ; GO SEARCH FILE DIRECTORY PHP 784 ; 785 LDA FCBOTC,X ; GET OPEN TYPE CODE 786 CMP #OPIN ; INPUT 787 BEQ  DFOIN 788 CMP #OPOUT ; OUTPUT 78 BEQ DFOOUT 790 CMP #OPIN+OPOUT  ; UPDATE 7 ? BEQ DFOUPD 792 CMP #OPOUT+OPAPND ; APPEND 793 BEQ DFOAPN  794 JMP ERDVDC ; ERROR ? ; 796 ; DFOIN - OPEN FOR INPUT  797 ; 798 DFOIN = * 7 99 PLP ; GET SEARCH FLAG 800 BCS OPNER1 ; ERROR IF NOT FOUND 801 BCC DFOUI 802 ; 803 ; DFOUPD - OPEN FOR UPDATE 804 ; 05 DFOUPD = * 806 PLP  ; GET SEARCH FLAG 807 BCS OPNER1 ; BR NOT FOUND 808 JSR TSTLOCK ; TEST LOCK 80 ;  810 DFOUI = * 811 JSR DFRDSU ; SET UP FOR READ 812 JMP GREAT ; DONE  81 ; 814 OPNER1 JMP ERFNF ; FILE NOT FOUND 815 .PAGE ;  1 ; DFOAPN - OPEN APPEND 818 ; 81 DFOAPN = * 820 PLP ; GET READ STATUS 821 BCS OPNER1 ; BR NOT FOUND 822 LDY CDIRD ; IF OLD LDA FILDIR+DFDFL1,Y ; FILE TYPE AND #DFDNLD ; THEN BEQ APOER ; ERROR JSR TSTLOCK ; TEST LOCKED 823 JSR OPVTOC ; READ VTOC JSR GETSECTOR ; GET A SECTOR  825 STA FCBSSN+1,X ; MOVE START SECTOR NUMBER 826 LDA FCBLSN,X ; TO START SECTOR NUMBER 827 STA FCBSSN,X ; 828  JMP DHFOX2 ; CONTINUE AS OPEN 82 APOER JMP ERAPO ; 830 ; DFOOUT - OPEN FOR OUTPUT 831 ; 832 DFOOUT = * 833 PLP ; GET SEARCH FLAG 834 BCS DFOX1 835 ; JSR XDEL0 ; DELETE THE FILE OR FILES 837 LDY CDIRD 838 JMP OPN1A  839 ; 840 DFOX1 = * 841 LDA DHOLES ; WAS THERE A HOLE 842 BMI OPNER2 ; BR IF NO HOLE 843 STA CDIRS ; SAVE HOLE SECTOR AS CURRENT DIR SECT 844 JSR RDDIR ; GO READ CURRENT DIR SECTOR  845 LDA DHOLED ; MOVE HOLE DISPL TO 846 STA CDIRD ; CUR DIR DISPL 8 LDA DHFNUM ; MOVE HOLE FN 848  STA SFNUM ; TO CURRENT 849 JSR OPVTOC LDY CDIRD LDX #10 LDA #$20 852 OPN1B STA FILDIR+DFDPFN,Y ;BLANK FILL FILE ENTRY FOR FILENAME INY DEX 854 BPL OPN1B 855 LDX CURFCB ;  856 OPN1A = * JSR GETSECTOR ; GET A SECTOR LDY CDIRD ; GET DIR DISPL STA FILDIR+DFDSSN+1,Y ; PUT SECTOR INTO DIR REC 860  LDA FCBLSN,X 861 STA FILDIR+DFDSSN,Y 862 ; 86 LDA #DFDINU+DFDOUT+DFDNLD ; SET DIR ENTRY IN USE STA FILDIR+DFDFL1,Y 865 LDA #0 ; SET NOT LOCKED 866 STA FILDIR+DFDCNT+1,Y ; SET COUNT = 0  867 STA FILDIR+DFDCNT,Y ; SET COUNT = 0 868 ; 869 LDX #0  870 OPN2 LDA FNAME,X ; MOVE FILE NAME 871 CMP #'? ; IF WILD CARD 872 BEQ OPN2A ; CHANGE TO BLANK STA FILDIR+DFDPFN,Y ; TO DIRECTORY 874 OPN2A = * INY 876 INX 877 CPX #11  878 BCC OPN2 879 ; 880 LDX CURFCB ; RESTORE X REG  881 JSR WRTDIR ; GO WRITE DIRECTORY 882 DHFOX2 = * 883 JSR SETFCB  884 JSR WRTN6 ; FIX UP AS IF WRITE 885 OPN3 LDA #FCBFAS ; SET NEW FILE 886 STA FCBFLG,X 887  JSR TSTDOS ; IF NOT DOS BNE DHFOX3 ; BR JMP WRTDOS ; ELSE DO IT DHFOX3 = * JMP GREAT 888 ;  889 OPNER2 JSR ERDFULL ; DIRECTORY FULL 8 0 ; 8 1 ;  892 SETFCB = * LDA #0 ; CLEAR STA FCBFLG,X ; FLAG 895 OPNF1 LDA SFNUM ; MOVE FILE # TO FCB 896 ASL A ; LEFT JUSTIFED FN 89 ASL A 89 STA FCBFNO,X 899 LDA #0  900 STA FCBDLN,X ; DATA LENGTH 901 STA FCBCNT,X ; SET CNT = 0 902 STA FCBCNT+1,X  903 RTS 904 DFRDSU JSR SETFCB ; SET UP FCB 905 LDY CDIRD ; MOVE START SECTOR TO LINK 906 LDA DFDFL1+FILDIR,Y ; SET NEW AND #DFDNLD ; SECTOR STA FCBSLT,X ; FLAG LDA FILDIR+DFDSSN,Y STA FCBLSN,X  908 LDA FILDIR+DFDSSN+1,Y 909 STA FCBLSN+1,X 910 JSR RDNS0 ; READ FIRST SECTOR  911 RTS ; DONE 12 .PAGE 'PUT BYTE' ; ; DFMPUT - PUT A FILE BYTE ; DFMPUT STA SVDBYT ; SAVE DATA BYTE LDA ICDNO,X STA ICDNO-IOCB+ZICB JSR SETUP ; GO SET UP LDY ENTSTK ; CHK TO SEE IF ENTRY WAS NOT FROM CIO LDA STAK,Y ; IF HI BYTE RETURN IS NOT IN OS ADDRESS CMP #OSBTM ; SPACE, THEN A NON-CIO ENTRY BCS FRMCIO ; BRANCH IF FROM CIO LDA #0 ; ELSE PREVENT DOING BURST I/O STA ICCOMZ FRMCIO LDA FCBOTC,X ; IF NOT OPEN AND #OPOUT ; OUTPUT BEQ PUTER ; ERROR LDY FCBDLN,X ; GET DATA LENGTH TYA CMP FCBMLN,X ; IF SECTOR NOT F1LL BCC PUT1 ; THEN BR JSR WRTNXS ; ELSE WRITE FULL SECTOR BCS PEOF ; BR IF EOF JSR WTBUR ; TEST BURST LDY #0 ; BCS PUT1 ; BR IF NO BURST LDA (ICBALZ),Y ; PUT NEXT BYTE STA SVDBYT ; AFTER BURST AREA ; PUT1 INC FCBDLN,X ; INC DATA LENGTH LDA SVDBYT ; GET DATA BYTE STA (ZSBA),Y ; AND PUT IN SECTOR BUFFER ; LDA #FCBFSM ; INDICATE SECTOR MODIFIED ORA FCBFLG,X STA FCBFLG,X ; JMP GREAT ; DONE ; PUTER JMP ERDVDC PEOF JMP ERREOF .PAGE 'BURST I/O' ; ; TEST BURST I/O AND DO IF POSSIBLE ; WTBUR LDA FCBFLG,X ; IF NOT ACQUIRING SECTORS  BPL NOBURST ; THEN UPDATE AND BMI TBURST ; NO BURST ; RTBUR LDA #0 ; SET READ TYPE ; TBURST STA BURTYP ; SET BURST TYPE LDA ICCOMZ ; IF COMMAND AND #2  ; IS TEXT MORE BEQ NOBURST ; THEN NO BURST ; JSR TBLEN ; IF USER BUFFER LESS BCS NOBURST ; THEN SECTOR, NO BURST ; LDA ICBALZ ; MOVE USER BUFFER STA  ZSBA ; ADR TO SECTPOR LDA ICBAHZ ; BUFFER PTR STA ZSBA+1 ; NXTBUR LDA BURTYP ; GET I/O TYPE BMI WRBUR ; BR IF WRITE ; JSR RDNXTS ; DO SECTOR READ  BCC BBINC ; BR IF EOF BCS BUREOF ; BR RD EOF ; NOBURST SEC ; INDICATE NO BURST RTS ; WRBUR LDA DRVMDL ; WRITE FULL SECTOR STA FCBDLN,X ; DATA COUNT ;  TAY LDA (ZSBA),Y ; SAVE DATA TO BE STA SVD1 ; TO BE CLOBBERED INY LDA (ZSBA),Y ; BY WRTNXS STA SVD2 INY LDA (ZSBA),Y STA SVD3 ;  JSR WRTNXS ; WRITE SECTOR ; LDY DRVMDL ; RESTORE CLOBBERED DATA LDA SVD1 STA (ZSBA),Y INY LDA SVD2 STA (ZSBA),Y INY LDA SVD3 STA  (ZSBA),Y ; ; BBINC CLC LDA ZSBA ; INC SECTOR ADC FCBMLN,X ; BUFFER ADR BY STA ZSBA ; ACTUAL DATA LEN LDA ZSBA+1 ; GOT OT PUT ADC #0 STA ZSBA+1 ; SEC LDA ICBLLZ ; DEC USER SBC FCBMLN,X ; BUFFER LEN BY STA ICBLLZ ; ACTUAL DATA LEN LDA ICBLHZ ; GOT OR PUT SBC #0 NOP STA ICBLHZ ; JSR TBLEN ; IF USER BUF LEN BCC NXTBUR ; NOW >= SECTOR, DO AGAIN ; BUREOF = * ; END OF BURSTING LDA ZSBA ; MOVE FINAL ADR BACK STA ICBALZ ; TO USER BUFFER PTR LDA ZSBA+1 STA ICBAHZ ; LDY FCBBUF,X ; RESTORE ZSBA DEY JSR SSBA ; BURST CLC ; INDICATE BURSTED RTS ; AND RETURN ; ; TEST USER BUF LEN FOR BURST ; TBLEN = * LDA DRVTYPE ; IF DRIVE NOT CMP #1 ; 128 BYTE SECTOR TYPE BNE TBL256 ; THEN DO 256 BYTE TEST ; LDA ICBLLZ ; IF 128 , MUST BY 128 BMI BURST ; OR MORE BYTES ; TBL256 LDA ICBLHZ ; IF BUF LEN HI >=256 BNE BURST ; THEN CAN BURST SEC ; ELSE INDICATE NO BURST RTS .PAGE 'GET BYTE' ; ; ; DFMGET - GET A FILE BYTE ; DFMGET = * JSR SETUP ; GO SET UP LDA FCBOTC,X ; IF OPEN FOR AND #OPDIR ; DIR CNT BEQ GET1 JMP GDCHAR ; THEN GO TO DIR ROUTINE ; GET1 LDA FCBDLN,X ; GET DATA LENGTH CMP FCBMLN,X ; TEST EMPTY SECTOR BCC GET2 ; BR IF NOT EMPTY JSR RTBUR ; DO BURST IF POSSIBLE JSR RDNXTS ; GET NEXT SECTOR BCC GET1 ; BR IF NOT EOF GEOF = * JMP ERREOF ; ELSE EOF ERROR ; GET2 TAY LDA (ZSBA),Y ; GET DATA BYTE STA SVDBYT ; SAVE THE BYTE INY ; INC DATA LENGTH TYA STA FCBDLN,X ; AND SET NEW VALUE EFLOOK = * LDY FCBLSN,X ; DO EOF LOOK AHEAD BNE GET3 ; IF LSN NOT ZERO LDY FCBLSN+1,X ; THEN BNE GET3 ; NOT EOF CMP FCBMLN,X ; IF LSN=0 THEN CHECK FOR BCC GET3 ; LAST BYTE LDA #$03 ; IF LAST BYTE THEN RTN JMP RETURN ; GET3 JMP GREAT .PAGE 'STATUS' ; ; DFMSTA - GET A FILE STATUS ; DFMSTA JSR SETUP ; SET UP JSR FNDCODE ; DECODE FILE NAME JSR SFDIR ; SEARCH FOR FILE BCS SFNF  ; BR NOT FOUND JSR TSTLOCK ; TEST LOCKED JMP GREAT ; FILE EXISTS & UNLOCKED ; SFNF JMP ERFNF .PAGE 'CLOSE' ; ; DFMCLOSE - CLOSE A FILE ; DFMCLS JSR SETUP ; SET UP LDA FCBOTC,X ; GET OPEN CODE AND #OPOUT ; IF NOT OUTPUT 995 BEQ CLDONE ; THEN DONE 996 ;  997 ROL FCBFLG,X ; IF NOT ACQUIRING SECTORS 998 BCC CLUPDT ; THEN IS UPDATE 999 ;  1000 JSR WRTLSEC ; WRITE LAST SECTOR 1001 ; 1002 JSR RRDIR ; GO GET DIRECTORY 1003 LDA FCBCNT+1,X ; GET COUNT OF SECTORS 1004 PHA 1005 LDA FCBCNT,X 1006 PHA  100 ; 1008 LDA FCBOTC,X ; GET OPEN CODE 1009 AND #OPAPND ; IF NOT APPEND 1010 BEQ CLOUT ; BR 1011 ; 1012 JSR DFRDSU ; ELSE SET UP FO R READ 1013 APP1 JSR RDNXTS ; READ TO EOF 1014 BCC APP1 ; C=SET ON EOR 1015 ; ! 1016 LDA FCBSSN,X ; MOVE START SECTOR 1017 STA FCBLSN,X ; TO EOF LINK SECTOR 1018 LDA FCBSSN+1,X 1019 " STA FCBLSN+1,X 1020 JSR WRTN2 ; THEN WRITE AS NOT EOF 1021 ; 1022 CLOUT LDY C#DIRD ; GET DIR DISPL 1023 CLC ; ADD DIR COUNT 1024 PLA ; TO ACQUIRE COUNT 1025 ADC FILDIR+DFDCNT,Y ;$ AND PUT BACK 1026 STA FILDIR+DFDCNT,Y 1027 PLA 1028 ADC FILDIR+DFDCNT+1,Y % 102 STA FILDIR+DFDCNT+1,Y 1030 ; 1031 LDA #DFDINU+DFDNLD ; SET ENTRY TO IN-USE & STA FILDIR+DFDFL1,Y 1033 JSR WRTDIR ; WRITE DIRECTORY 1034 JSR WRTVTOC ; WRITE VTOC 1035 ; ' 1036 CLDONE LDA #0 ; CLEAR OPEN CODE 1037 STA FCBOTC,X 1038 JMP FGREAT ; DON(E 1039 ; 1040 CLUPDT = * ROL FCBFLG,X ; IF SECTOR NOT MODIFIED 1042 BCC CLDONE ; T)HEN DONE 1043 JSR WRCSIO ; ELSE WRITE IT 1044 JMP CLDONE ; THEN DONE 1045 ; * 1046 .PAGE ; 1048 ; RE-READ DIR RECORD 1049 ; + 1050 RRDIR = * 1051 LDA FCBFNO,X ; GET FILE NUMBER 1052 LSR A ; RE-ADJUST IT , 105 LSR A 105 STA SFNUM ; PUT INTO SFNUM 1055 ; 1056 ; - 1057 JSR FNSHFT ; SET ACU = FILE NO./64 1058 STA CDIRS ; TO GET DIR SECTOR 1059 JSR FNS.HFT ; SET ACU TO REM * 16 1060 JSR FNSHF1 1061 ASL A 106 STA CDIRD ;/ TO GET DIR DISPL 1063 ; 1064 JMP RDDIR 1065 FNSHFT LDA #0 0 1066 FNSHF1 LDY #3 ; SHIFT 3 BITS OF 1067 FNSHF2 ASL FCBFNO,X ; FILE NO INTO ACU 1068 ROL A 1 106 DEY 1070 BNE FNSHF2 1071 RTS 1072 2 .PAGE 'DEVICE DEPENDENT COMMAND' ; ; DFMDDC - DEVICE DEPENDENT CMND EXECUTION ; DFMDDC JSR SETUP ; SET UP FOR EXECUTION LDA ICCOM,X ; GET COMMAND CMP #254 ; IS IT FORMAT 3 BEQ XFV ; BR IF CMP #MAXDDC ; TEST RANGE BCS DVDCER ; BR OUT OF RANGE SEC SBC #$20 ; SUBTRACT $20 BCC DVDCER ; BR OUT OF RANGE ASL 4 A ; MULT RESULT BY 2 TAY ; USE AS INDEX LDA DVDCVT,Y PHA ; PUSH EXECUTION ADR LDA DVDCVT+1,Y PHA ; TO STACK AND GOTO 5 RTS ; VIA RTS ; DVDCVT .DBYTE XRENAME-1 ; 20 - RENAME .DBYTE XDELETE-1 ; 21 - DELETE .DBYTE DVDCER-1 ; INVALID CMND .DBYTE XLOCK-1 ; 23 - LOCK .DBYTE XUNLOCK-1 6 ; 24 - UNLOCK .DBYTE XPOINT-1 ; 25 - POINT .DBYTE XNOTE-1 ; 26 - NOTE ; MAXDDC = $27 ; MAX DVDC PLUS 1 ; DVDCER JMP ERDVDC XFV JMP XFORMAT ; FORMAT VECTOR .PAGE 'RENAME' ; ;7 XRENAME - RENAME A FILE OR FILES ; XRENAME JSR FNDCODE ; DECODE FILE NAME STY TEMP2 ; SAVE FNAME INDEX JSR SFDIR ; GO FIND FILE IN DIR BCC XRN1 ; BR IF FOUND 8 JMP ERFNF ; XRN1 JSR TSTLOCK ; TEST LOCK JSR TSTDOS ; IF NOT DOS BNE XRN1A ; THEN JSR DELDOS ; DON'T CHANGE S0 XRN1A LDY TEMP2 ; GET INDEX FO9R END FN1 JSR FNDCNX ; GO DECODE NEXT FILE NAME JSR TSTDOS ; IF NOT DOS BNE XRN1B ; THEN LDY CDIRD LDA FILDIR+DFDSSN+1,Y PHA LDA FILDIR+DFDSSN,Y : TAY ; A,Y NEW DOS PLA ; START SECTOR JSR SETDSO ; GO WRITE SECTOR 0 ; XRN1B LDX #0 LDY CDIRD ; XRN2 LDA FNAME,X ; MOVE FILE NAME ;CMP #'? ; FROM FNAME TO DIR ENT BEQ XRN3 ; BUT DON'T CHANGE WILD CARD STA FILDIR+DFDPFN,Y ; CHARS INDICATED IN FNAME XRN3 INY INX CPX #11 BCC XRN2 LDX CURF ; SEARCH DIR FOR FILE NAME 1149 BCS DFNF ; BR NOT FOUND 1150 XDELX = * 1151 JSR XDEL0 ? 1152 JSR TSTDOS BNE XDELY JSR DELDOS XDELY ; 1153 XDEL3 JSR WRTDIR ; WRITE DIR ENTRY @ 1154 JSR CSFDIR ; LOOK FOR NEXT MATCH 1155 BCC XDELX ; BR IF FOUND 1156 JSR WRTVTOC 1157 A JMP FGREAT 1158 ; 1159 XDEL0 JSR OPVTOC ; 11B61 XDEL1 LDY CDIRD ; GET DIR DISPL 1162 JSR TSTLOCK ; GO TEST LOCK 1163 LDA #DFDEDE ; LOAD DELETED FLAG 1164 STA C FILDIR+DFDFL1,Y ; DELETE FILE 1165 ; 1166 JSR DFRDSU 1167 JMP XDEL2A D 1168 ; 1169 XDEL2 JSR RDNXTS ; READ NEXT SECTOR 1170 BCS XDEL4 E 1171 XDEL2A = * JSR FRESECT ; FREE CURRENT SECTOR 1173 JMP XDEL2 1174 ; XDEL4 = * LDY #DVDWRQF ; TURN ON WRITE REQ'D LDA #$FF ; ON VTOC BUFFER STA (ZDRVA),Y RTS 1176 ; G 1177 DFNF JMP ERFNF ; FILE NOT FOUND 1178 .PAGE 'LOCK AND UNLOCK' ; ; XLOCK - LOCK A FILE ; XUNLOCK - UNLOCK A FILE ; XLOCK LDA #DFDLOC ; SET LOCK STA THEMP4 BNE XLCOM ; GO TO COMMON XUNLOCK LDA #0 ; SET UNLOCK STA TEMP4 ; XLCOM JSR FNDCODE ; DECODE FILE NAME JSR SFDIR ; FIND FIRST MATCH BCC XLC1 I ; BR MATCH FOUND JMP ERFNF ; BR NOT FOUND ; XLC1 LDY CDIRD ; GET CURRENT DISPL LDA FILDIR+DFDFL1,Y ; GET LOCK BYTE AND #$DF ; TURN OFF LOCK ORA TEMP4 J ; OR IN LOCK/UNLOCK STA FILDIR+DFDFL1,Y ; SET NEW LOCK BYTE JSR WRTDIR ; GO WRITE ; JSR CSFDIR ; LOOK FOR NEXT MATCH BCC XLC1 ; BR FOUND JMP FGREAT ;ELSKE DONE ; ; TSTLOCK - TEST FILE LOCKED ; TSTLOCK LDY CDIRD ; GET DIR DISPL LDA FILDIR+DFDFL1,Y ; LOAD LOCK BYTE AND #DFDLOC ; MASK LOCK BIT BNE TLF ; BR IF LOCKED L RTS ; ELSE RETURN ; TLF JMP ERFLOCK .PAGE 'POINT' ; ; XPOINT - POINT REQUEST ; XPOINT LDA FCBFLG,X ; IF ACQ SECTORS BMI PERR1 ; POINT INVALID LDA ICAUX4,X M ; IF REQUEST IS NOT CMP FCBCSN+1,X ; SAME AS CURRENT BNE XP1 ; THEN BR LDA ICAUX3,X CMP FCBCSN,X BEQ XP2 ; ELSE NO NEED TO CHANGE ; XP1 LDA FCBFLG,X N ; IF NOT MODIFIED BEQ XP1A ; BR JSR WRCSIO ; ELSE WRITE IT LDA #0 STA FCBFLG,X XP1A = * LDA ICAUX4,X STA FCBLSN+1,X LDA ICAUX3,X O STA FCBLSN,X JSR RDNS0 ; READ REQ SECTOR BCS XPERR ; XP2 LDA ICAUX5,X ; TEST REG DATA LENGTH CMP FCBMLN,X ; LESS THAN MAX BCC XP3 BEQ XP3 XPERR = * P JMP ERRPDL ; IF NOT, THEN ERROR ; XP3 STA FCBDLN,X ; SET NEW DATA LENGTH JMP GREAT ; DONE ; PERR1 JMP ERRPOT ; INVALID POINT OPEN .PAGE 'NOTE' ; ; XNOTE - EXECUTE NOQTE REQUEST ; XNOTE LDA FCBDLN,X ; DATA LENGTH VALUE STA ICAUX5,X ; TO AUX 2 LDA FCBCSN,X ; CUR SEC NO (LOW) STA ICAUX3,X ; TO AUX 3 LDA FCBCSN+1,X ; CUR SEC NO R(HIGH) STA ICAUX4,X ; TO AUX 4 JMP GREAT ; DONE .PAGE 'FORMAT' ; ; XFORMAT - FORMAT A DISKETTE ; XFORMAT LDA ZSBA+1 ; MOVE VTOC BUF ADR STA DCBBUF+1 ; TO DCB S LDA ZSBA STA DCBBUF LDA #DCBCFD ; FORMAT STA DCBCMD ; TO DCB LDA #$40 ; TELL SIO RECEIVING DATA STA DCBSTA LDX DRVTYP ; GET DRIVE TYTPE - 128 OR 256 LDA #$31 ; BUS ID LDY DSKTIM ; GET FORMAT TIME OUT VALUE JSR DSIO2 ; GOTO LOCAL DISK HANDLER- THEN SIO ; BPL XF0 IF NO ERRORS CONTINUE FORMAT U CPY #$90 ELSE CHECK FOR A DEVICE DONE ERROR BNE XFERR NO, THEN ERROR EXIT ; TSTFMT = * ELSE CHECK FOR BAD SECTOR INFO LDY #0 RETURNED BY CONTROLLER LDA #$FVF CMP (ZSBA),Y BNE XFBAD BAD SECTORS, RETURN ERR MSG INY CMP (ZSBA),Y BEQ XFERR NOT BAD SECTOR ERR, REG ERR EXIT XFBAD JMP ERDBAD ; XFERR LDA DCBSTA GET ERRWOR STATUS JMP RETURN DO ERROR EXIT ; XF0 LDA #0 TAY XF1 STA (ZDRVA),Y INY BPL XF1 ; LDY #0 ; SET LDA #2 ; TYPE = 2 STA (ZDXRVA),Y INY LDA #$C3 ;SET MSN AND STA (ZDRVA),Y ;NSA = 707 = 2C3 INY INY STA (ZDRVA),Y LDA #$02 DEY STA (ZDRVA),Y INY INY Y STA (ZDRVA),Y ; LDY #DVDSMP LDA #$FF ; SET SECTOR MAP TO XF2 STA (ZDRVA),Y ; ALL ONES INY CPY #DVDSMP+90 BNE XF2 ; LDA #$0F ; DEALLOCATE FIRST 4Z SECTORS LDY #DVDSMP ; FOR BOOT STA (ZDRVA),Y ; LDY #DVDSMP+45 ; DEALLOCATE MIDDLE 9 LDA #0 ; SECTORS STA (ZDRVA),Y ; FOR INY ; VTOC [& FILE DIR LDA #$7F STA (ZDRVA),Y ; JSR WRTVTOC ; WRITE THE VTOC ; LDA #0 ; ZERO FILL DIRECTORY SECTORS TAY XF3 STA FILDIR,Y ; USE FILE DIRECTORY BUFFER \INY BPL XF3 ; LDA #7 ; WRITE TO ALL 8 DIRECTORY SECTORS STA CDIRS XF4 JSR WRTDIR DEC CDIRS BPL XF4 ; JSR DELDOS ; SET NO DOS ; JMP FGREAT ] ;DONE .PAGE 'LIST DIRECTORY' ; ; LISTDIR - LIST THE DIRECTOR ; GDCHAR - GET NEXT DIR CHARACTER ; ; THE DIRECTORY IS LISTED VIA OPEN ; LIST DIRECTORY FUNCTION. EACH DIR ; ENTRY THAT ^MATCHES THE FILE SPEC ; IS CONVERTED TO A PRINTABLE FORMAT ; INTO A SECTOR BUFFER. THE GET BYTE ; ENTRY IS USED TO GET THE PRINTABLE ; CHARACTERS ONE AT A TIME. THE ; LAST LINE PRIN_TED IS ALWAYS A ; COUNT OF THE NUMBER OF SECTORS IN USE ; AND THE NUMBER REMAINING AVAIABLE SECTORS. ; LISTDIR LDA #0 STA TEMP4 JSR SFDIR ; SEARCH FOR A FILE NAME BCC `LDENT1 ; BR IF FOUND BCS LDCNT ; BR IF NOT FOUND ; GDCHAR BIT TEMP4 ; TEST FLAG BMI LDDONE ; BR IF ALL DONE ; LDY TEMP4 ; GET COUNT OF CHARS SENT LDAa (ZSBA),Y ; GET NEXT CHAR STA SVDBYT ; IN SVDBYT INC TEMP4 ; INC COUNT CMP #EOL ; TEST IF EOL DONE BNE GDCRTN ; BR NOT EOL CPY #17 b; WAS THIS AN ENTRY BCS LDENT ; BR IF IF WAS LDA #$80 ; ELSE INDICATE END STA TEMP4 ; IN TEMP4 ; GDCRTN JMP GREAT ; DONE ; LDENT LDA #0 ;CLEAR CHAR COUNcTER STA TEMP4 JSR CSFDIR ;SEARCH FOR NEXT MATCH BCS LDCNT ;BR NO MORE MATCHES LDENT1 JSR FDENT ;FORMAT ENTRY JMP GREAT ;DONE ; LDCNT JSR RDVTOC d ;READ VTOC LDY #DVDNSA+1 ;GET NUMBER SECTOR AVR LDA (ZDRVA),Y PHA DEY LDA (ZDRVA),Y TAY PLA ; JSR CVDX ;AND CONVERT ; LDY #3 ;e SET EOL LDX #FSCML-1 ; PUT IN CUTE MVFSCM LDA FSCM,X ; MSG STA (ZSBA),Y INY DEX BPL MVFSCM JSR CVDY ; LDA #0 ;SET CHAR COUNT STA TfEMP4 JMP FGREAT ;DONE ; LDDONE JMP ERREOF ; END OF FILE ; FSCM .BYTE 'SROTCES EERF ' FSCML = *-FSCM .PAGE ; ; FORMAT DIR ENTRY INTO A SECTOR BUFFER ; FDENT LDY #0 g ;START AT BUF DISPL 0 LDA #$20 ;START WITH A BLANK STA (ZSBA),Y LDX CDIRD LDA FILDIR+DFDFL1,X AND #DFDLOC ; BUT IF FILE LOCKED BEQ LD1 LDA #'* h ;CHANGE TO AST STA (ZSBA),Y LD1 INY LDA #$20 ;FOLLOWED BY A BLANK STA (ZSBA),Y INY ; LD2 LDA FILDIR+DFDPFN,X ;MOVE THE 12 CHAR STA (ZSBA),Y ;FILE NAME IiNX INY CPY #13 BCC LD2 ; LDA #$20 ;FOLLOWED BY A BLANK STA (ZSBA),Y INY STY TEMP4 ;SAVE INDEX = 15 ; LDX CDIRD LDY FILDIR+DFDCNT,X ;jSET A,Y LDA FILDIR+DFDCNT+1,X ; = SECTOR COU(T ; CVDX LDX #100 ;CONVERT AND MOVE JSR CVDIGIT ;100S DIGIT LDX #10 JSR CVDIGIT ;10S DIGIT TYA JSR SkTDIGIT ;1S DIGIT ; LDY #17 ; THEN PUT OUT CVDY LDA #EOL ;AND EOL STA (ZSBA),Y LDY #0 ; SET CHAR CNT =0 STY TEMP4 RTS ;DONE FORlMAT ; CVDIGIT STX TEMP3 ;SAVE DIGIT VALUE LDX #$FF ; CVD1 STA TEMP2 ;SAVE CUR VALUE HI STY TEMP1 ;AND LOW INX ;INC DIGIT COUNTER SEC m ;SUBTRACT DIGIT VALUE LDA TEMP1 ;FROM CUR VALUE SBC TEMP3 TAY LDA TEMP2 SBC #0 BCS CVD1 ;IF NOT GONE MINUS, DO AGAIN ; TXA ;DIGIT TO ACnU STDIGIT ORA #$30 ;PLUS ASCII ZERO LDY TEMP4 ;GET OUTPUT INDEX STA (ZSBA),Y ;AND SET DIGIT INC TEMP4 ;INC OUTPUT INDEX LDA TEMP2 ;LOAD VALUE HI oLDY TEMP1 ;AND VALUE LOW RTS ;AND RETURN .PAGE 'FILE NAME DECODE' ; ; FNDCODE - DECODE A FILE NAME ; THE USER FILENAME IS POINTED TO BY ; ZBUFP, IT IS OF THE FORM P.X WpHERE P ; IS THE PRIMARY FILE NAME (1 TO 8 CHARS) ; AND X IS THE EXTENDED FILE NAME ; (0 TO 4 CHARS). THE PERIOD IS OPTIONAL ; (IF NOT PRESENT, THEN NO EXTENSION). THE ; DECODED FILEq NAME WILL BE 12 CHHARS ; IN LENGTH. THE P FIELD WILL BE ; LEFT JUSTIFIED IN THE FIRST 8 BYTES. THE ; X FIELD WILL BE LEFT JUSTIFIED IN THE LAST ; 4 BYTES. BLANKS ARE USED TO PAD THE ; r FIELDS TO FULL SIZE. IF THE USER SPECIFIED ; P OR X FIELDS CONTAIN MORE THEN 8 OR 4 ; CHARS, THAN THE EXTRA CHARS ARE IGNORED. ; THE '*' WILD CARD CHAR WILL CAUSE THE ; REST OF THE FIELDS TO sBE FILLED WITH THE ; '?' WILD CARD CHAR. ANY NON-ALPHANUMERIC ; CHARACTER TERMINATES THE FILENAME. ; FNDCODE LDA ICBAL,X STA ZBUFP LDA ICBAH,X STA ZBUFP+1 LDY #2 t ;FIND THE D FD0A LDA (ZBUFP),Y ; DEY BMI FDNERR ;BR IF 256 CHARS SEEN CMP #': BNE FD0A FD0B INY ; FNDCNX LDX #11 ; CLEAR FILENAME TO BLANKS u LDA #$20 FD0 STA FNAME,X DEX BPL FD0 ; LDX #0 ; SET FNAME CHAR COUNT = 0 STX EXTSW ; SET NOT IN EXTENSION ; ; FD1 INY ; INC ZBUFP INDEX LDvA (ZBUFP),Y ;GET BUFFER CHAR ; CMP #'* ; TEST FOR WILD CARDS BNE FD3 ; BR NOT WILD CARD ; FD2 LDA #'? ; LOAD ? WILD CARD JSR FDSCHAR ; GO STORE IT wBCC FD2 ; BR IF PORX NOT FULL BPL FD1 ; BR IF AT START OF X BMI FDEND ; BR IF AT X END ; FD3 CMP #'. ; WAS CHAR FIELD SEPERATOR BNE FD4 ; BR IF NOTx BIT EXTSW ; WAS THERE ALREADY ONE PERIOD BMI FDEND ; BR IF WAS (END) LDX #8 ; ADV FNAME INDEX TO X FIELD ROR EXTSW ; SET EXTSW = MINUS BCC FD1 y ; CONTINUE WITH NEXT CHAR ; FD4 CMP #'? ; WAS IT WILD CARD BEQ FD6 ; BR IF WILD CARD ; CMP #'A ; IS CHAR ALPHA BCC FD5 ; BR NOT ALPHA CMP #$5B z ; TEXT HI ALPHA BCC FD6 ; BR IF ALPHA ; CHAR NOT ALPHA FD5 CPX #0 ; IF FIRST CHAR NOT BEQ FDNERR ; ALPHA THEN ERROR ; CMP #$30 { ;IS CHAR NUMERIC BCC FDEND ; BR NOT NUMERIC (END OF NAME) CMP #$3A ;TEST NUMERIC HI BCS FDEND ; BR NO NUMBER ; FD6 JSR FDSCHAR ; STORE THE CHAR JMP FD1 | ; AND CONTINUE WITH NEXT ; FDEND LDX CURFCB ; RESTORE X REG RTS ; AND RETURN ; FDNERR JMP ERRFN ; INDICATE FILE NAME ERROR .PAGE ; ; FDSCHAR - STORE FILE NAME CHAR ; } ON ENTRY A = CHAR ; X = NEXT FN POSITION ; ON EXIT CARRY - SET IF FIELD FULL ; MINUS - IF START OF EXECTION ; PLUS - IF END OF EXECTION ; FDSCHAR CPX #8 ; AT EXTENS~ION BCC FDSC2 ; BR IF NOT BEQ FDSC1 ; BR IF FIRST CHAR OF ; CPX #12 ; AT END OF EXIT BCC FDSC2 ; BR NOT AT END RTS ; RTN : PLUS, CARRY SET ; FDSC1 BIT EXTSW ; DO NOT STORE CHAR UNLESS BMI FDSC2 ; PERIOD WAS SEEN RTS ; RTN : MINUS, CARRY SET ; FDSC2 STA FNAME,X ; SET CHAR INTO NAME INX  ; INC TO NEXT CHAR CLC RTS ; RTN : CARRY CLEAR .PAGE 'DIRECTORY SEARCH' ; ; SFDIR - SEARCH FILE DIRECTORY ; CSFDIR - FILE DIRECTORY SEARCH ; ; THE FILE DIRECTORY IS SEARCHED FOR THE ; FILENAME IN FNAME. THE SEARCH STARTS ; AT THE CENTRAL SECTOR+1 AND WILL CONTINUE ; FOR UP TO A TOTAL OF EIGHT SECTORS. WHEN ; TESTING FOR FMANE MATCH, '?' FNAME. ; CHARS WILL ALLWAYS MATCH THE CORESPONDING ; DIR FILE NAME CHAR. IF A MATCH IS FOUND ; CDIRS CONTAINS THE RELATIVE DIRECTORY SECTOR ; NUMBER (0 -7) AND CDIRD (AND THE Y REG) ; CONTAIN THE DISPLACEMENT OF THE ENTRY. AFTER ; A MATCH HAS BEEN FOUND, THE DIRECTORY CAN ; BE SEARCHED FOR ANOTHER MATCH VIA THE CSFDIR ; ENTRY POINT. IF A MATCH HAS NOT BEEN FOUND, ; THEN DHOLES AND DHOLED WILL POINT TO A ;  DIRECTORY HOLE THAT CAN BE USED. IF DHOLES = FF ; THEN THE DIRECTORY IS FULL. THE CARRY ; IS RETURN CLEAR IF FILE FOUND, SET IF FILE ; NOT FOUND. ; SFDIR LDA #$FF ; INIT TO -1 STA DHOLES ; DIR HOLE SECTOR STA CDIRS ; CUR DIR SECTOR STA SFNUM ; FILE NUMBER LDA #$70 ; INIT TO -16 (-ENTRY LENGTH) STA CDIRD ; CUR DIR DISPL ; CSFDIR INC SFNUM CLC LDA CDIRD ; CDIRD = CDIRD + ENTRY LENGTH ADC #DFDELN BPL SFD2 ; IF RESULT < 128 THEN BR ; ELSE AT END OF DIR SECT  INC CDIRS ; INC TO NEXT DIR SECTOR LDA #8 ; TEST END OF DIR CMP CDIRS BCC SFD1 ; BR NOT END BEQ SDRTN ; SFD1 JSR RDDIR ; READ THE NEXT DIR RECORD LDA #0 ; SET DIR DISPL = 0 ; SFD2 STA CDIRD ; SET NEW DIR DISPL TAY ; PUT DISPL IN Y AS INDEX ; LDA FILDIR+DFDFL1,Y ; GET FLAG 1 BEQ SFDSH ; BR IF UNUSED (END OF USED ENTRIES) BMI SFDSH ; BR IF DELETED AND #DFDOUT ; IF OPEN OUTPUT BNE CSFDIR ; DON'T FIND IT ; ENTRY IN USE, TEST FOR MATCH LDX  #0 ; TEST MATCH ON 12 CHARS SFD3 LDA FNAME,X ; FILE NAME CHAR CMP #'? ; IF FNC IS WILD CARD BEQ SFD4 ; THEN IT MATCHES CMP FILDIR+DFDPFN,Y ; ELSE IT MUST MATCH FOR REAC BNE CSFDIR ; IF NOT MATCH THEN TRY NEXT SFD4 INX ; INC CHAR CNT INY CPX #11 ; TEST ALL BNE SFD3 ; AND CONTINUE CHECK ; CLC ; WE HAVE A MATCH BCC SDRTN ; SFDSH ; WE HAVE A HOLE LDA DHOLES ; IF DHOLES NOT MINUS BPL SFDSH1 ; THEN ALREADY HAVE A GOOD HOLE ; ELSE LDA CDIRS ; MOVE CURRENT DIR SECTOR STA DHOLES ; AND CURRENT DIR DISPL LDA CDIRD ; TO HOLE SECTOR AND DISPL STA DHOLED LDA SFNUM ; SAVE HOLE STA DHFNUM ; FILE NUMBER ; SFDSH1 LDA FILDIR+DFDFL1,Y ; IF HOLE WAS A DELETED BMI CSFDIR ; ENTRY THEN CONTINUE ; ELSE WE ARE AT END OF SEC ; USED ENTRIES THUS FILE NOT FOUND SDRTN LDX CURFCB ; RESTORE X REG RTS ; AND RETURN .PAGE 'WRITE DATA SECTOR' ; ; WRTNXS - WRITE NEXT SECTOR ; WRTNXS LDA FCBFLG,X ; IF ACQUIRING SECTORS BMI WRTN1  ; THEN NOT UPDATE ; ASL A ; IF SECTOR NOT MODIFIED BPL WRU1 ; THEN DON'T IT ; ASL A STA FCBFLG,X ; TURN OFF FLAG BITS JSR WRCSIO ; WRITE CURRENT SECTOR BMI WRNERR ; BR IF BAD I/O WRU1 JMP RDNXTS ; ELSE READ NEXT SECTOR ; WRTN1 JSR GETSECTOR ; GET A NEW SECTOR ; WRTLSEC LDA FCBDLN,X ; GET DATA LENGTH WRTLS1 LDY DRVLBT ; INTO LAST BYTE STA (ZSBA),Y ; OF SECTOR ; WRTN2 LDA FCBLSN+1,X ; MOVE LINK SECTOR ORA FCBFNO,X ; PLUS FILE NUM LDY DRVMDL ; TO BYTES 126,127 STA (ZSBA),Y ; OF SECTOR BUFF INY LDA FCBLSN,X STA (ZSBA),Y ; JSR WRCSIO ; WRITE SECTOR BPL WRTN5 ; BR NOT ERROR ; WRNERR LDA DCBSTA ; SAVE ERROR STATUS STA TEMP4 LDA  #0 ; CLOSE FILE STA FCBOTC,X LDA TEMP4 ; RECOVER ERROR CODE JMP RETURN ; GO RETURN ; WRTN5 INC FCBCNT,X ; INC SECTOR CNT BNE WRTN6 INC FCBCNT+1,X WRTN6 JSR MVLSN ; LINK TO CUR LDA #0 STA FCBLSN,X ; LINK = 0 STA FCBLSN+1,X STA FCBDLN,X ; DLN = 0 LDA DRVMDL STA FCBMLN,X WRNRTS CLC RTS ; DONE ; WRCSIO SEC ; WRITE CUR SECTOR RWCSIO LDA FCBCSN+1,X LDY FCBCSN,X JMP DSIO ; MVLSN LDA FCBLSN,X ; MOVE LINK STA FCBCSN,X LDA  FCBLSN+1,X STA FCBCSN+1,X RTS ; .PAGE 'READ DATA SECTOR' ; ; RDNXTS - READ NEXT SECTOR ; RDNXTS LDA FCBFLG,X ; IF NOT UPD MODE BEQ RDNS0 ; BR JMP WRTNXS ; ELSE WRITE FIRS\ RDNS0 = * LDA FCBLSN,X ; IF LSN NOT ORA FCBLSN+1,X ; ZERO BNE RDNS1 ; BR SEC ; ELSE EOF RTS RDNS1 JSR MVLSN ; MOVE LINK TO CURRENT CLC ; READ JSR RWCSIO ; CURRENT SECTOR BMI RDIOER ; BR IF OK READ ; ELSE GO TO I/O ERROR ; LDY DRVMDL LDA (ZSBA),Y ; TEST FOR SAME AND #$FC ; FILE NO CMP FCBFNO,X BNE RDFNMM ; IF NOT, THEN ERR ; LDA (ZSBA),Y ; MOVE LINK SECTOR AND #$03 STA FCBLSN+1,X INY LDA (ZSBA),Y STA FCBLSN,X ; ; INY ; INC TO LEN BYTE LDA (ZSBA),Y ; GET LEN BYTE PHA ; SAVE IT LDA FCBSLT,X ; GET SECTOR LEN TYPE BNE RDNS3 ; BR IF NEW TYPE ; PLA ; GET LEN BMI RDNS2 ; BR IF OLD SHORT SECTOR LDA #125 ; ELSE SET FULL SECTOR RDNS2 AND #$7F ; TURN OFF MSB PHA ; BALANCE STACK ; RDNS3 PLA STA FCBMLN,X ; SET MAX LENGTH ; LDA #0 ; SET CUR DATA LENGTH = 0 STA FCBDLN,X CLC RTS ; DONE RDIOER JSR ERRIO ; I/O ERROR RDFNMM ; FILE NUMBER MISMATCH LDA ICCOM,X CMP #$21 ; WAS THIS DELETE BEQ RDDELE ; BR IF DELETE JSR ERFNMM  ; BR NOT DELETE RDDELE SEC ; INDICATE EOF TO DELETE RTS .PAGE 'READ/WRITE DIR' ; ; RDDIR/WRDIR - READ/WRITE DIRECTORY ; RDDIR CLC ; SET READ BCC DIRIO ; WRTDIR SEC  ; SET WRITE ; DIRIO PHP ; SAVE READ/WRITE LDA #.HIGH.FILDIR ; MOVE BUF ADR STA DCBBUF+1 ; TO DCB LDA #.LOW.FILDIR STA DCBBUF ; CLC LDA CDIRS ; CDIRS+ ADC #$69 ; ((40*18)/2)+1 TAY ; INTO A,Y LDA #1 ; IS DIR SECTOR NO ADC #0 ; JMP DSYSIO ; GO DO SYSTEM I/O .PAGE 'READ/WRITE VTOC' ; ; RDVTOC/WRCTOC - READ/WRITE VTOC ; RDVTOC LDY #DVDWRQ ; IF WRITE REQD LDA (ZDRVA),Y BEQ RDVGO RTS RDVGO CLC ; SET READ BCC VTIO ; WRTVTOC WRVTOC LDY #DVDWRQ ; TURN OFF LDA #0 ;WRITE REQD STA (ZDRVA),Y SEC ; ; VTIO PHP ; SAVE R/W LDA ZDRVA+1 ; MOVE BUF ADR STA DCBBUF+1 ; TO DCB LDA ZDRVA STA DCBBUF ; LDY #$68 ; READ SECTOR LDA #1 ; (40*18)/2 ; DSYSIO PLP DSYSIA LDX DRVTYP ; LOAD DRIVE TYPE JSR BSIO ; GO DO I/O BMI DSIOER ; BR IF ERROR RTS ; RETURN ; ; DSIOER CMP #DCBDER ; WAS IT DATA ERRR BEQ DEAD ; BR IF WAS JMP ERRIO ; ELSE USER PROBLEM ; DEAD JMP ERRSYS  ; FATAL ERROR ; ; OPEN VTOC ; OPVTOC JSR RDVTOC ; READ IT JMP WRTVTOC ; THEN WRITE IT ; INSURES NOT PROTECTED .PAGE 'FREE SECTOR' ; ; FRESECT - FREE CURRENT SECTOR ; FRESECT LDA FCBCSN,X ORA FCBCSN+1,X BEQ FSRTS LDA #0 LDY #3 ; DIVIDE SECTOR # FS1 LSR FCBCSN+1,X ; BY 3 TO GET BYTE NO ROR FCBCSN,X ; IN THE SECTOR MAP ROR A ; WITH REM IN ACU DEY BNE FS1 ; LDY #5 FS2 ROR A ; TO FOR BYTE BIT NO DEY BNE FS2 ; TAY ; BIT NO (0 TO 7) INTO Y LDA #0 SEC ; SHIFT IN A BIT FS3 ROR A ; TO PROPER LOCCATION DEY BPL FS3 PHA ; SAVE MASK LDA FCBCSN,X ; GET BYTE NO ADC #DVDSMP ; ADD OFFSET TO SMAP TAY ; RESULT IS VTOC INDEX ; PLA ; GET BIT MASK ORA (ZDRVA),Y ; OF BIT TO BITMAP STA (ZDRVA),Y ; AND SET RESULTS ; LDY #DVDNSA ; INC NO SECTORS AVAIL LDA (ZDRVA),Y CLC ADC #1 STA (ZDRVA),Y INY LDA (ZDRVA),Y ADC #0 STA (ZDRVA),Y ; FSRTS =  * RTS ; DONE .PAGE 'GET SECTOR' ; ; GET SECTOR - GET A FREE SECTOR FOR USE IN FCB AT X REG. ; THE SECTOR NUMBER IS PLACED IN FCBLSN. ; ; THE SEARCH FOR A FREE SECTOR STARTS AT THE ; DVDSMP BYTE. SECTOR ARE NUMBERED SEQUENTIALLY ; FROM ZERO TO MAXSM WITH THE LEFT BIT ; OF THE DVDSMP BEING WITH ZERO. ; GETSECTOR LDY #DVDSMP-1 ;SET Y TO START MAP-1 ; GS1 INY ;INC SMAP INDEX CPY  #90+DVDSMP ;AT END OF MAP BCS GSERR ;BR IF AT END LDA (ZDRVA),Y ;GET A MAP BYTE BEQ GS1 ;BR NO FREE SECTOR IN BYTE ; STY TEMP1 ;SAVE MAP INDEX PHA  ; DEC NO SECTORS AVAIL SEC LDY #DVDNSA LDA (ZDRVA),Y SBC #1 STA (ZDRVA),Y INY LDA (ZDRVA),Y SBC #0 STA (ZDRVA),Y ; INY  ; SET WRITE REQD LDA #$FF STA (ZDRVA),Y ; PLA LDY #$FF ;SET BIT COUNTER=-1 ; GS2 INY ;SHIFT MAP BYTE ASL A ;UNTIL A FREE SECTOR  BCC GS2 ;FOUND STY TEMP2 ;SAVE BIT NUMBER GS3 LSR A ;AND SHIFT BYTE DEY ; BACK TO IT'S ORIGNAL BPL GS3 ;POSITION AND PUT IT LDY  TEMP1 ; BACK INTO THE MAP STA (ZDRVA),Y ; ; SEC ;SECTOR MAP BYTE LDA TEMP1 ;=DISPL-DVDSMP SBC #DVDSMP ; LDY #0 STY TEMP1 ;CLEAR SECT NO HI ; GS4 ASL A ;MULT REL SECTOR MAP ROL TEMP1 ;BYTE NO BY 8 INY CPY #3 BCC GS4 ; CLC ADC TEMP2 ;ADD BIT NO TO STA FCBLSN,X  ;SECTOR NUMBER LDA TEMP1 ;AND PUT INTO ADC #0 ;FCBLSN STA FCBLSN+1,X ; RTS ;DONE ; GSERR JMP ERRNSA ;NO SECTOR AVAIL .PAGE 'SETUP ROUTINE' ; ; SETUP - A ROUTINE USED FOR ALL COMMANDS TO SETUP FMS ; CONTROL CELLS TO ACESS A PARTICULAR FILE ; SETUP LDA #$9F ; INIT ERROR CODE STA ERRNO ; TO ZERO STX CURFCB ; SAVE FCB ; TSX ; SAVE ENTRY STACK INX INX STX ENTSTK ; LDX CURFCB ; GET CURRENT FCB LDY ICDNOZ ; MOVE DRIVE NO STY DCBDRV ; TO DCB  DEY ; DEC FOR ACCESS TO TABLES LDA DBUFAL,Y ; MOVE DRIVE BUFFER STA ZDRVA ; ADR TO ZZRO PAGE PTR LDA DBUFAH,Y STA ZDRVA+1 ; LDA DRVTBL,Y ; GET DRIVE TYPE BEQ DERR1 ; BR IF NOT EXIST STA DRVTYP ; SAVE TYPE ; TAY ; MOVE MAX DATA LEN LDA DRVMDL,Y ; AND LAST SECTOR BYTE STA DRVMDL ; DISPL TO START OF LDA DRVLBT,Y ; TABLES STA DRVLBT ; LDY FCBBUF,X ; GET SECTOR BUF NO. DEY ; DEC TO ACCESS TBL BPL SSBA ; BR IF ONE IS ALLOCATED ; LDY #0 ; IF NONE ALLOCATED GSB1 LDA SECTBL,Y ; TRY TO FIND ONE BEQ GSB4 ; BR ONE FOUND GSB2 INY ; DEC TRY COUNT CPY #16 BCC GSB1 ; BR MORE TO TRY ; GSB3 JMP ERRNSB ; NO SECTOR BUFFERS AVAIABLE ; GSB4 LDA DRVTYP ; FOUND ONE, IF 256 BYTES LSR A ; DRIVE NEED TO CONT BCS GSB5 ; BR NOT 256 BYTES INY  ; ELSE TRY NEXT CONTIG CPY #16 ; TEST END OF BUFFERS BCS GSB3 ; AND BR IF NO MORE LDA SECTBL,Y ; ELSE SEE IF ITS THREE BNE GSB2 ; BR NOT FREE DEY ;  LDA #$80 ; ALLOCATE SECOND OF TWO STA SECTBL+1,Y ; GSB5 LDA #$80 ; ALLOCATE FIRST OR ONLY STA SECTBL,Y TYA STA FCBBUF,X ; PUT BUF NO INTO FCB INC FCBBUF,X ; INC BUF NO SO NOT ZERO ; SSBA LDA SABUFL,Y ; MOVE BUFFER ADR STA ZSBA ; TO ZERO PAGE PTR LDA SABUFH,Y STA ZSBA+1 ; ; RTS ; DERR1 JMP ERRDNO ; BAD DRIVE NO .PAGE ; ; FREE SECTOR BUFFERS ; FRESBUF = * LDY FCBBUF,X ; GET BUF NO BEQ FSBR ; BR IF NONE DEY ; DEC FOR TBL ACCESS LDA #0 ; FREE STA FCBBUF,X ; IN FCB STA SECTBL,Y ; AND TABLE LDA DRVTYP ; IF 128 BYTE LSR A ; DRIVE BCS FSBR ; FREE ONLY ONE LSR A  ; ELSE STA SECTBL+1,Y ; FREE TWO FSBR RTS .PAGE .PAGE 'DATA SECTOR I/O' ; ; DSIO - DATA SECTOR I/O ; DSIO PHA ; SAVE ACU DATA LDA ZSBA ; WRITE SECTOR BUF STA DCBBUF ; ADR MOVED TO LDA ZSBA+1 ; DCB STA DCBBUF+1 PLA ; RESTORE ACU ; LDX DRVTYP JSR BSIO ; DO THE I/O RTS .PAGE 'WRITE DOS' ; ; WRTDOS - WRITE DOS TO DISK ; WRTDOS LDY FCBCSN,X ; MOVE START ADR LDA FCBCSN+1,X JSR SETDSO ; WRITE SECTOR ZERO JSR WD0 ; WRITE DOS JMP GREAT ; DELDOS LDA #0 ; SET FILE NOT EXISTS DD1 STA DFSFLG ; WRTSC0 LDA #.HIGH.FMSORG ; MOVE FMS START STA DCBBUF+1 ; ADR TO DCB LDA #.LOW.FMSORG STA DCBBUF ;  LDA #0 ; CLEAR SECTOR NO TO ZERO STA DCBSEC STA DCBSEC+1 ; WRNBS INC DCBSEC ; INC SECTOR NO. LDX #1 ; GET DRIVE TYPE SEC JSR BSIOR ; DO THE WRITE ; ; CLC LDA DCBBUF ; INC SECTOR ADDR ADC #128 STA DCBBUF LDA DCBBUF+1 ADC #0 STA DCBBUF+1 ; LDA DCBSEC ; TEST FOR WRITE CMP  BRCNT ; OF ALL BOOT SECTORS BNE WRNBS ; BR NOT ALL ; RTS ; SETDSO STY DFLINK ; SET LINK START STA DFLINK+1 ; LDA DRVTYP STA DFSFLG LDY DRVMDL STY BLDISP BNE DD1 ; GO WRITE SECTOR ZERO .PAGE WD0 LDA DFLADR ; MOVE FILE START ADR STA ZBUFP ; TO ZBUFP LDA DFLADR+1 STA ZBUFP+1 ; WD1 LDY  #0 ; MOVE 125 WD2 LDA (ZBUFP),Y ; BYTES OF DOS STA (ZSBA),Y ; TO SECTOR BUFFER INY CPY DRVMDL BCC WD2 TYA STA FCBDLN,X ;SET DATA LENGTH ; JSR INCBA ; INCREMENT ZBUFP BY 125 CMP SASA+1 ; IF NOT END OR BCC WD3 ; PAST END OF DOS BNE WD4 ; THEN WRTNXS LDA ZBUFP ; ELSE CMP SASA  ; DONE BCC WD3 BNE WD4 ; WD3 JSR WRTNXS ; WRITE NEXT SECTOR JMP WD1 ; WD4 RTS ; RETURN, CLOSE WILL WRITE FINAL SECTOR ; AND RETURN ;  .PAGE 'TEST DOS FILE NAME' ; ; TSTDOS - TEST FOR DOS SYS FILENAME ; TSTDOS LDY #11 ; LOOK AT 12 CHARS TDF1 LDA FNAME-1,Y ; TEST DECODED FILE NAME CHAR CMP DFN-1,Y ; WITH DOS FILE NAME CHAR BNE TDFR ; BR NOT MATCH DEY BNE TDF1 ; BR IF MORE, ELSE RTN EQ TDFR RTS ; RETURN ; DFN .BYTE 'DOS SYS ' .PAGE 'ERROR ROUNTINES AND RETURN' ; ; ERROR ROUTINES ; ERDBAD INC ERRNO ; BAD SECTOR AT FORMAT TIME ERAPO INC ERRNO ; ATTEMPT APPEND TO OLD TYPE FILE ERRPOT INC ERRNO ; POINT INVALID ERFNF INC ERRNO ;FILE NOT FOUND ERDFULL INC  ERRNO ;DIRECTORY FULL ERDVDC INC ERRNO ;DEVICE COMMAND INVALID ERFLOCK INC ERRNO ;FILE LOCKED ERRPDL INC ERRNO ; POINT DATA LENGTH ERRFN INC ERRNO ;FILE NAME ERROR ERFNMM INC ERRNO ; FILE NUMBER MISMATCH ERRSYS INC ERRNO ;FATAL SYSTEM DATA I/O ERROR ERRNSA INC ERRNO ;NO SECTOR AVAIL ERRNSB INC ERRNO ;NO SECTOR BUFFERS AVAIL ERRDNO INC ERRNO ;DRIVE NO ERROR ; LDA ERRNO ;GET ERROR NUMBER RETURN LDX CURFCB ;GET CUR FCB NO STA ICSTA,X ; PUT IN ICB LDX ENTSTK ;GET ENTRY STACK PTR TXS ;AND RESTORE LDX CURFCB TAY LDA SVDBYT ;GET SAVED DATA BYTE RTS ;AND RETURN ; ERRIO LDA DCBSTA ;GET I/O ERROR CODE BMI RETURN ;AND RETURN ; FGREAT LDX CURFCB JSR FRESBUF ; FREE SECTOR BUFFER GREAT LDA #01 ;SET ALL OK BNE RETURN ;AND RETURN ERREOF LDA #$88 ; SET EOF CODE BMI RETURN ; GO RETURN .PAGE 'MISC STORAGE' ; ; MISC NON ZERO .PAGE STORAGE AREA ; DRVMDL .BYTE 0 ; MAX DATA LEN .BYTE 125 ; 128 BYTE SECTOR .BYTE 253 ; 256 BYTE SECTOR ; DRVLBT .BYTE 0 ; DISPL TO LAST SECTOR BYTE  .BYTE 127 ; 128 BYTE SECTOR .BYTE 255 ; 256 BYTE SECTOR DRVTYP *=*+1 ; DRIVE TYPE RETRY *=*+1 ; I/O RETRY COUNTER ENTSTK *=*+1 ;ENTRY STACK LEVEL CURFCB *=*+1 ;CURRENT FCB (IOCB ALSO) DHOLES *=*+1 ; DIR HOLE SECTOR DHOLED *=*+1 ; DIR HOLE DISPL DHFNUM *=*+1 ; DIR HOLE FILE NO. CDIRD *=*+1 ; CUR DIR DISPL CDIRS *=*+1 ; CUR DIR SECTOR SFNUM *=*+1 ; FILE NUMBER SVDBYT *=*+1 ; SAVED OUTPUT DATA BYTE SVD1 *=*+1 ; SAVE DATA BYTES SVD2 *=*+1 ; FOR WRITE BURST SVD3 *=*+1 EXTSW ; FNDCODE EXTENSION FLAG TEMP1 *=*+1 ; TEMP1 TEMP2 *=*+1 ; TEMP2 TEMP3 *=*+1 ; TEMP3 TEMP4 *=*+1 ; TEM4 BURTYP *=*+1  ; BURST I/O TYPE ; DRVTBL *=*+8 ; DRIVE TABLE SECTBL *=*+16 DBUFAL *=*+8 ; VTOC BUFFER DBUFAH *=*+8 ; PTR FOR DRIVE N SABUFL *=*+16 ; SECTOR BUFF SABUFH *=*+16 ; FOR SECTOR N FNAME *=*+12 ;FILE NAME AFNAME *=*+12 ; AUXILLARY FILE NAME ; MDRV *=*+1 ; MAX DRIVE NO. ; Z = * *= $1381 ;PUT ON SAME BOUNDARY AS PRODUCTION ;VERSION DONE ON 11/34 .PAGE 'FILE CONTROL BLOCKS' ; ; FILE CONTROL BLOCK ; ONE FILE CONTROL BLOCK IS USED FOR EACH ; OPEN FILE. THE RELATILE FCB USED ; RELATES DIRECTLY TO THE IOCB NUMBER ; THAT OPENED THE FILE. THUS THERE ARE ; EIGHT FCBS. THE FCBS ARE(CONVIENTLY) ; THE SAME SIZE AS IOCBS. EACH FCB ; CONTAINS ALL THE IMFORMATION REQUIRED TO ; CONTROL THE PROCESSING OF AN OPEN FILE ; FCB FCBFNO  *=*+1 ;FILE NUMBER LEFT JUSTIFIED FCBOTC *=*+1 ;OPEN TYPE CODE *=*+1 ; SPARE FCBSLT *=*+1 ; FLAG FOR NEW SECTOR LEN TYPE FCBFLG *=*+1 ;WORKING FLAG FCBMLN *=*+1 ; MAX SECTOR DATA LENGTH FCBDLN *=*+1 ;CURRENT SECTOR BUFFER DATA LENGTH FCBBUF *=*+1 ; SECTOR BUFFER NO FCBCSN *=*+2 ;CURRENT SECTOR NUMBER FCBLSN *=*+2  ;LINK/ALLOCATE SECTOR NUMBER FCBSSN *=*+2 ; START SECTOR NU7BE[ (?A&PEN: FCBCRS ; CURRENT FILE RELATIVE SECTOR NUMBER FCBCNT *=*+2 ; SECTOR CNT FCBLEN = *-FCB ;FCB LENGTH ; *=FCBLEN*7+* ; ALLOCATE 7 MORE FCBS ; ; OPEN CODE BITS ; - USED IN IOCB AUX1 ; - AND FCBOTC ; OPIN = $04 ; INPUT OPOUT = $08 ; OUTPUT OPDIR = $02  ; LIST DIRECTORY OPAPND = $01 ; APPEND ; FCBFAS = $80 ; FCBFLG - ACQ SECTORS FCBFSM = $40 ; FCBFLG - SECTOR MODIFIED .PAGE 'FILE DIRECTORY' ; ; DISK FILE DIRECTORY ; -THE FILE DIRECTORY OCCUPIES 8 CONSECUTIVE SECTORS ; STARTING AT THE CENTRAL SECTOR+1. EACH ; FILE DIRECTORY SECTOR CONTAINS EIGHT ENTRIES. ; THE IS ONE ENTRY FOR EACH NAMED FILE. THE ; ARE A TOTAL OF 64 NAMED FILES PER VOLUME ; ; THE FILE NUMBER IS USED THROUGH OUT THE ; SYSTEM IS THE RELATIVE (TO ONE) FILE ; DIRECTORY ENTRY NUMBER. ; ; THE EQUATES BELOW ARE FOR A SINCE NAMED FILE ENTRY ; DFDFL1 = 0 ;FLAG1 (1) DFDCNT = 1 ; SECTOR COUNTER (LOW) DFDSSN = 3 ;START SECTOR NO. (2) DFDPFN = 5 ;PRIMARY FILE NAME (8) DFDXFN = 13 ;EXTENDED FILE NAME (4) DFDELN = 16 ;ENTRY LENGTH ; ; DFDFL1 VALUE EQUATE ; DFDEUU = 0 ;ENTRY UNUSED DFDEDE = $80 ;ENTRY DELETED DFDINU = $40 ; ENTRY IN USE DFDOUT = $01 ;FILE OPEN FOR OUTPUT DFDLOC = $20 ; ENTRY LOCKED DFDNLD =  $02 ; FILE HAS NEW TYPE SECTOR LEN BYTE ; FILDIR *=*+256 ;RESUME FILE DIR SPACE .PAGE 'VOLUME DIRECTORY' ; ; ; ; DISK VOLUME DIRECTORY ; THE VOLUME DIRECTORY OCCUPIES THE CENTRAL ; VOLUME SECTOR. THE VOLUME DIRECTORY CONTAINS ; INFORMATION PARTAINING TO THE ENTIRE ; DISKETTE VOLUME. ; ; THE LABELS BELOW MAP THE VOLUME ; DIRECTORY SECTOR. ; DVDTCD = 0 ;VOLUME DIRECTORY TYPE CODE (1) ;  ;USED TO DELINATE MAJOR (1) ; ;FMS SYSTEM FORMAT CHANGES ; DVDMSN = 1 ; MAX SECTOR NUMBER (2) DVDNSA = 3 ; NO SECTORS AVAIABLE ; DVDWRQ = 5 ; WRITE REQUIRED DVDSMP = 10 ;SECTOR MAP START ; ;EACH BIT REPRESENTS ; ;A SECTOR. IF THE BIT ; ;IS ON THEN THE SECTOR ; ;IS FREE AND AVAILABLE. IF ; ;THE BIT IS OFF, THE ; ;SECTOR IS IN USE OR ; ;BAD. THE MOST SIGNIFICANT ; ;BIT OF THE FIRST BYTE IS ;  ;SECTOR ZERO. ; DHADR CVECT1 JMP $0000 VECTOR FOR CORVUS DISK HANDLER CVECT2 JMP $0000 VECTOR FOR CORVUS SIO ROUTINE CVECT3 JMP DRVTBL VECTOR POINTS TO FMS DRIVE-TABLE ; *=*+$400-9 LEAVE 1K OF RAM FOR CORVUS ROUTINES ; ; ; .PAGE 'END OF FMS' ENDFMS = * .END ; REQUIRED TO INTERFACE WITH THE APPLE 13 SECTOR ; FORMAT DISK. THE DCB IS USED FOR COMMUNICATION ;  WITH THE FILE MANAGEMENT SYSTEM. THE IOB ; IS USED TO COMMUNICATE WITH APPLES READ/WRITE ; TRACK SECTOR (OR 'KORE ROUTINES') ; *= DHADR A13SDH LDA DCBCMD ; LOAD DCB COMMAND  CMP #DCBCST ; TEST AT STATUS BNE ADFMT ; BR IF NOT STATUS ; ADGIO LDA #DCBSOK ; STATUS REQUEST STA DCBSTA ; REPORT OK RTS ; RETURN ; ADFMT  ; FORMAT REQUEST CMP #DCBCFD BNE ADCRW ; BR NOT FORMAT LDA #IBCFD ; LOAD FORMAT COMMAND STA IBCMD JSR ADIO1 ; DO FORMAT LDA #IBCWS ; THEN WRITE ALL SECTORS STA IBCMD LDA #34 STA IBTRK ADF2 LDA #12 STA IBSECT ADF1 JSR ADIO1 DEC IBSECT BPL ADF1 DEC IBTRK BPL ADF2 BMI  ADGIO ; ADCRW ; READ/WRITE REQUEST LDA #IBCRS STA IBCMD JSR CONVTS ; CONVERT ABS SECTOR NO TO ; ; APPLE TRACK/SECTOR STA IBTRK STY IBSECT JSR ADIO1 LDA DCBCMD LDY #IBCRS CMP #DCBCRS BEQ ADCRW1 LDY #IBCWS ADCRW1 STY IBCMD ; ; SO JUST SET IT ; ADIO LDA #IBCWS  CMP IBCMD BNE ADIOX JSR ADWBUF ADIOX JSR ADIO1 ; BCS ADBIO ; BR IF BAD I/O ; LDA #80 ; GET BYTE COUNT = 128 STA DCBCNT LDA #0 STA DCBCNT+1 LDA #IBCRS CMP IBCMD BNE ADGIO JSR ADRBUF JMP ADGIO ; ADBIO LDA IBSTAT ; GET AD STATUS ; LDX #DCBWRP ; TRY WRITE PROTECT CMP #IBSWP BEQ ADBS ; BR IF WRITE PROTECT LDX #DCBDER ; ELSE IS READ ERROR ; ADBS STX DCBSTA ; SET READ ERROR LDA #0 ; SET BYTE COUNT =0 STA DCBCNT STA DCBCNT+1 RTS ; DONE ; ; CONVTS - CONVERT ABS SECTOR TO TRACK/SECTOR ; - ACU = TRACK = ABS SECTOR/13 ; - Y = SECTOR = REM ; CONVTS LDA DCBSEC ; USE APPLES DIVIDE ROUTINE  STA $50 LDA DCBSEC+1 STA $51 LDA #$1A STA $54 LDA #0 STA $52 STA $53 STA $55 JSR $FB84 LDA $50 LSR $52 LDY  $52 RTS ADWBUF JSR ADBUF ADWB1 LDA ($50),Y STA ADSB,X INX INY BPL ADWB1 RTS ADRBUF JSR ADBUF ADRB1 LDA ADSB,X STA ($50),Y INX INY BPL ADRB1 RTS ADBUF LDX #0 LDA DCBSEC ROR A BCC ADBUF1 LDX #$80 ADBUF1 LDY #0 LDA DCBBUF STA $50 LDA DCBBUF+1 STA $51  RTS ; ADSB *=*+256 ADIO1 LDA DCBDRV ; MOVE DRIVE NUMBER STA IBDRVN LDA #0 ; SET TRACK = 0 STA IBVOL LDA #.HIGH.ADSB STA IBBUFP+1 LDA #.LOW.ADSB STA IBBUFP ; LDA #.HIGH.IOB LDY #.LOW.IOB JSR $BD00 ; GO DO I/O RTS .PAGE 'IOB' *= $B7E8 ; ; IOB - INPUT/OUTPUT BLOCK ; INTERFACE THE DISK HANDLER TO ; THE APPLE 13 SECTOR RWTS ; IOB IBTYPE *=*+1 ; IOB TYPE CODE IBSLOT *=*+1 ; CONTROLLER SLOT NO IBDRVN *=*+1 ; DRIVE NO IBVOL *=*+1 ; VOLUME NO IBTRK *=*+1 ; TRACK NUMBER IBSECT *=*+1 ; SECTOR NUMBER IBDCTP *=*+2 ; DEVICE CONTROL TABLE PTR IBBUFP *=*+2 ; BUFFER POINTERS IBDLEN *=*+2 ; DATA LENGTH IBCMD *=*+1 ; COMMAND IBSTAT *=*+1 ; I/O STATUS IBSMOD *=*+1 ; STATUS MODIFIER IBPSLT *=*+1 ; PREVIOUS SLOT IBPDRV *=*+1 ; PREVIOUS DRIVE IBSPAR *=*+1  ; SPARE ; ; IBCMD VALUE EQUATES ; IBCRS = $01 ; READ SECTOR IBCWS = $02 ; WRITE SECTOR IBCFD = $04 ; FORMAT DISK ; ; IBSTAT VALUE EQUATES ; IBSRE = $80  ; READ ERROR IBSDE = $40 ; DRIVE ERROR IBSWP = $10 ; WRITE PROTECT ; .ENDIF .PAGE 'GLOP' .END .TITLE 'DISK UTILITY PROGRAMS (DUP) VER 2.9 11/18/80' LIST X ; ; ;CHANGED FOR SYSTEM RESET -- DUPFLG ;ADDED INTERRUPT ROUTINES FROM SIO -- KB ;ADDED SAVE/RESTORE OF DOSINI VECTOR -- KB ; ;******************************************************************************* ; THIS IS FINAL VERSION OF DUP ---- 2.0S ---- ;****************************************************************************** ; ; FILENAME = DOS2.DUP20S ON TANDEM ; .PAGE ; **** EQUATES **** ; ; ; CIO = $E456 DKHND = $E453 SETVBV = $E45C SYSVBV = $E45F XITVBV = $E462 CIOINV = $E46E MEMTOP = $2E5 BRKKEY = $11 DOSVEC = $A DOSINI = $C ;DOS INIT VECTOR WARMST = 8 LMARGN = $52 RMARGN = $53 CARTST = $BFFA INTRVEC = $20A ;INTERRUPT VECTOR LOC FOR SIO PATCH MEMLO = $2E7 SHFLOK = $2BE INITAD = $2E2 RUNAD = $2E0 ICHIDZ = $20 ICDNOZ =  $21 ICBALZ = $24 ICBAHZ = $25 ICIDNO = $2E MAXDEV = $21 HATABS = $31A USRDOS = $1700 FMS = $700 FMINIT = FMS+$E0 DOS = FMS+$E40 WRMSTR = $E474 ;WARM START VECTOR BSIOR = $772 ;ENTRY POINT TO FMS DISK HANDLER USED BY DUP DISK CDTMV3 = $21C ;ADDRESS OF SYSTEM TIMER # 3 CDTMF3 = $22A ;ADDRESS OF SYS TIMER # 3 TIME OUT FLAG ; CR = $9B CUP =  $1C CDN = $1D CLF = $1E CRT = $1F DLL = $9C CLSCR = $7D EOF = $88 ;ENDFILE RETURN CODE FROM CIO ; ; OPEN = $03 CLOSE = $0C PUTCHR = $0B GETCHR = $07 GETREC = $05 PUTREC = $09 RENAME = $20 DELETE = $21 FORMAT = $FE LOCK = $23 UNLOCK = $24 STAREQ = $53 ;STATUS COMMAND TO DISK CONTROLLER ; IOCB1 = $10 ; DVSTAT = $2EA  ;ADDRESS OF STATUS INFO STORED BY OS ; ; DCB = $300 DUNIT = DCB+1 DCOMND = DCB+2 DSTATS = DCB+3 DBUFLO = DCB+4 DBUFHI = DCB+5 DSLO = DCB+$A DSHI = DCB+$B ; IOCB = $340 ICHI D = IOCB+0 ICDNO = IOCB+1 ICCOM = IOCB+2 ICSTA = IOCB+3 ICBAL = IOCB+4 ICBAH = IOCB+5 ICBLL = IOCB+8 ICBLH = IOCB+9 ICAX1 = IOCB+10 ICAX2 = IOCB+11 ; SYSED = $0 OWRI T = $08 ORDWRT = $0C ; HILO .MACRO P1 P1&H = P1&/256 P1&L = (-256)*&P1&H+&P1 .ENDM .PAGE ; **** ZERO PAGE VARIABLES **** ; ; *= $18 JMPTBL: .RES 2 RAMLO: .RES 2 BUFADR =  RAMLO ;SAVE AREA FOR BUFFER ADDRESS USED BY USEPGM .PAGE ; **** INIT CODE FOR DUP **** ; ; ; INITIALIZATION CODE FOR DUP - CALLS FMS INIT CODE. ; CALLED ON WARM START AND COLD START. ; *= DOS LDA  #0 STA OPT LDA #.LOW.MNDUPL STA DOSVEC LDA #.LOW.MNDUPH STA DOSVEC+1 LDA #.LOW.ISRSIR ;SET UP INTERRUPT VECTORS FOR SIO PATCH. STA INTRVEC ;INSTEAD OF USING THE SERIAL INPUT READY LDA #.HIGH.ISRSIR ;SERVICE ROUTINE AND THE SERIAL OUTPUT STA INTRVEC+1 ;INTERRUPT SERVICE ROUTINE IN THE OS ROM LDA #.LOW.ISRODN ;USE THE VERSIONS IN RAM FOLLOWING THE STA  INTRVEC+2 ;RESIDENT PORTION OF DUP. LDA #.HIGH.ISRODN STA INTRVEC+3 JSR FMINIT LDA WARMST ;ON COLDSTART, LOAD AUTORUN.SYS BNE CKMDOS ;WARMSTART CHECK IF DUP WAS RUNNING LDA #.LOW.AFL STA ICBAL+$10 LDA #.LOW.AFH STA ICBAH+$10 JSR INITX ;CLEAR DUPFLG SHOW DUP NOT IN MEMORY. LDA #$C0 JSR STLOAD ;LOAD, INIT AND RUN THE AUTORUN FILE JMP CLOSX ;MAKE SURE IOCB #1 IS CLOSED & RETURN ; CKMDOS LDA DUPFLG ;SEE IF DUP WAS IN MEMORY BEQ INITX ;=ZERO THEN WASN'T ; LDA MEMFLG ;SEE IF USER AREA WRITTEN TO MEM.SAV BEQ CLDSET ;=ZERO THEN WASN'T JSR LDMEM1 ;ELSE GET USER MEMORY BACK IN ; JSR RELDIN ;RELOAD SAVED DOSINI VECTOR JSR INITX ;CLEAR DUP IN MEMORY FLAG  JSR WRMSTR ;REDO WARMSTART ; INITX LDA #0 ;SAY DUP NOT IN MEMORY STA DUPFLG ;CLEAR FLAG RTS ; CLDSET STA WARMST ;NO VALID USER MEMORY BEQ INITX ;SET TO COLD START .PAGE ; **** LOADER ROUTINE **** ; ; ; LOADS FROM THE FILE (MUST BE LOAD FORMAT) ; INTO MEMORY. RETURNS: ; X=0 LOAD OK ; X=1 OPEN ERRORS Y=CIO CODE ; X=2 READ ERRORS Y=CIO CODE ; X=3 BAD LOAD FILE ; ON ENTRY, IOCB 1 POINTS TO FILENAME. ; DUPFLG .BYTE 0 ;FLAG -IF DUP IN MEMORY NOT ZERO OPT .BYTE 0 ;HOLDS VALUE OF OPTION GIVEN BY USER LOADFG .BYTE 0 ;FLAG = $80 IF MEMORY FILE DOESN'T HAVE TO BE LO HDBUF: .RES 4 HILO HDBUF SFLOAD LDA #$80 STLOAD STA LOADFG LOAD LDA #.LOW.RTS STA RUNAD LDA #.HIGH.RTS STA RUNAD+1 ;MAKE RUN AT EOF DEFAULT TO RTS LDX  #$10 LDA #OPEN STA ICCOM,X LDA #4 ;OPEN TYPE=INPUT STA ICAX1,X JSR CIO ;TRY TO OPEN FILE BPL RDLF ;CONT IF OK LDA #1 ;OPEN ERRORS BNE CLFX ;CLOSE AND EXIT RDLF LDX #$10 LDA #.LOW.DBUFL STA ICBAL,X LDA #.LOW.DBUFH STA ICBAH,X LDA #2 STA ICBLL,X LDA #0  STA ICBLH,X STA MEMLDD ;CLEAR MEM.SAV LOADED FLAG LDA #GETCHR STA ICCOM,X JSR CIO BMI ERST ;IF ERRS LDA #$FF CMP DBUF ;CHECK FOR VALID LOAD FILE BNE LNLF CMP DBUF+1 BNE LNLF ;BRANCH IF NOT A LOAD FILE RDDRC LDX #$10 LDA #.LOW.HDBUFL STA ICBAL,X LDA #.LOW.HDBUFH STA ICBAH,X LDA #4 RDDRC1 STA ICBLL,X LDA #0 STA ICBLH,X JSR CIO ;NO ERROR CHECK SO CAN CATCH EOF BPL STOK ;IF NO ERROR CPY #$88 ;SEE IF EOF BNE ERST  ;IF SOME ERROR STATUS ; ;EOF SO DONE, EXIT ; JSR CLOSX ;CLOSE IOCB'S 1 AND 2 BIT OPT BMI DRUN ;BRANCH IF NO RUN OPTION JSR JMPRUN ;JUMP THROUGH RUN VECTOR DRUN LDA #0 ;OK STATUS BIT LOADFG ;WAS MEMORY SWAPPED? STA LOADFG BMI CLFX ;BRANCH IF MEMORY WASN'T SWAPPED JSR MEMSVQ ;DOES MEMORY SAVE FILE EXIST? BMI DRUN1 ;BRANCH IF NOT PLA PLA JMP GOOD ;WRITE MEMORY AND RELOAD DUP ; ; SEE IF DUP WRITTEN OVER. IF IS RELOAD & TELL USER NEED MEM.SAV TO ; LOAD THIS FILE. ; DRUN1 LDA DUPFLG ;SEE IF DUP CLOBBERED BNE DRUN2 ;NO, THEN RETURN LDA #.LOW.NMSFL ;ELSE TELL USER NEED MEM.SAV LDX #.LOW.NMSFH JSR PRNTMSG ;PRINT MSG JMP RRDUP ;RELOAD & RUN DUP ; ;  RETURN TO CALLING ROUTINE ; DRUN2 LDA #0 ;NO DUP ERR MSG ON EOF CLFX TAX RTS RTS ; ; ERROR RETURNS ; LNLF JSR CLOSX LDA #3 ;BAD LOAD FILE BNE CLFX ERST TYA PHA ! JSR CLOSX PLA TAY BNE CLFX ; ; CONTINUE WITH LOAD - CHECK LOAD ADDRESS FOR HEADER ; HEADER IF HAVE CONCATENATED LOAD FILES ; STOK LDX #$10 LDA HDBUF ;MOVE PARAMS TO IOCB " STA ICBAL,X PHA LDA HDBUF+1 STA ICBAH,X TAY PLA INY ;WAS ADDRESS FF? BNE ADOK ;BRANCH IF NOT TAY INY ;OTHER #BYTE FF? BNE ADOK ;BRANCH IF NOT ; ; HAVE A HEADER & START ADDRESS - GET END ADDRESS FOR TEXT & DO AGAIN ; LDA HDBUF+2 STA HDBUF LDA HDBUF+3 STA HDBUF+1 ;MOVE LOAD ADDR$ESS LDA #.LOW.HDBUF+2 STA ICBAL,X LDA #.HIGH.(HDBUF+2) STA ICBAH,X ;SO LOAD ADDRESS DOESN'T GET WIPED OUT BY END AD LDA #2 JMP RDDRC1 ; ; GET LENGTH OF TEXT. THEN DETE%RMINE IF IN DUP ; ADOK LDA HDBUF+2 SEC SBC HDBUF STA ICBLL,X LDA HDBUF+3 SBC HDBUF+1 STA ICBLH,X LDA HDBUF+1 JSR AWDQ ;IS BEGINNING ADDRESS WIT&HIN DUP? BCS AWD ;BRANCH IF SO LDA HDBUF+3 JSR AWDQ ;IS ENDING ADDRESS WITHIN DUP? BCS AWD ;BRANCH IF SO ; ; SINCE TEXT IN DUP, LOAD MEM.SAV IF NECCESARY ; ANWD 'LDA MEMLDD BMI AWD ;BRANCH IF MEM.SAV ALREADY LOADED LDA #$80 ORA LOADFG STA LOADFG ;SET MEM.SAV DOESN'T HAVE TO BE LOADED FLAG AWD INC ICBLL,X BNE *+5 (INC ICBLH,X BIT LOADFG ;DOES MEMORY HAVE TO BE LOADED BMI DLM ;BRANCH IF NOT LDA MEMLDD ;WAS MEM.SAV ALREADY LOADED? BMI DLM ;BRANCH IF SO DEC MEML)DD JSR LDMEM ;LOAD MEM.SAVE FILE (IF IT EXISTS) LDA #0 ;SHOW USER AREA NOT DUP IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOS IN VECTOR FROM SAVED LOC ; ; SET NO INIT AD*DR DEFAULT THEN READ IN TEXT & ATTEMPT INIT ; DLM LDX #$10 LDA #.LOW.RTS STA INITAD LDA #.HIGH.RTS STA INITAD+1 ;INIT DEFAULTS TO AN RTS JSR CIO ;READ DATA DIRECTLY T+O MEMORY BPL DLM1 JMP ERST ;IF ERRORS DLM1 BIT OPT BMI DINIT ;BRANCH IF NO GO OPTION JSR JMPINT ;DO INIT DINIT JMP RDDRC ;GET NEXT SECTION OF LOAD FILE ,; ; SUBROUTINE TO DETERMINE IF ADDRESS IS WITHIN DUP ADDRESS SPACE. ; ENTRY - HI BYTE OF ADDRESS IN REG. A ; RETURNS - CARRY SET : WITHIN DUP ; CARRY CLR : NOT WITHIN DUP ; AWDQ CMP #.LOW.NDOSH BCC AW-DQR ;BRANCH IF HI BYTE LT DUP START CMP #.LOW.NMDUPH+1 ROL A EOR #1 LSR A ;COMPLEMENT CARRY AWDQR RTS ; ; JMPINT JMP (INITAD) JMPRUN JMP (RUNAD) ; ; MEMLDD .BYTE 0 AF. .BYTE 'D1:AUTORUN.SYS',CR HILO AF NMSF .BYTE 'NEED MEM.SAV TO LOAD THIS FILE.',CR HILO NMSF .PAGE ; **** CREATE MEM.SAV FILE **** ; ; ;ROUTINE WRITTEN BY M.E., APRIL 21,1980 ;THIS ROUTINE CREATES A FILE ON/ DISK OF DATA FROM MEMORY ;CREATE FILE CALLED 'D1:MEM.SAV', SET Y=1 ; ;ABLE TO CREATE FILE THEN SET REG.Y=ERROR RETURNED FROM CIO ;THE RAM TO BE OCCUPIED BY DUP IS STORED BY THIS ROUTINE INTO ;'MEMORY.SAV' ; ; NAME .BYTE 'D1:MEM.SAV',CR HIL0O NAME MWRITE JSR CLOSX ;CLOSE IOCB AND OPEN IT TO WRITE LDA #OWRIT ; STA ICAX1,X ; JSR OREST ;OPEN FOR WRITE BMI ERRWR ;IF ERROR THEN JMP AND RET ; ;1 ;WRITE MEMORY BLOCK ; LDA #PUTCHR STA ICCOM,X LDA #.LOW.NDOSL ;STORE START OF BLOCK FOR CIO STA ICBAL,X LDA #.LOW.NDOSH ;START ADDR (HIGH) STA ICBAH,X LDA #.LOW2.MLENL+1 ;LENGTH OF BLOCK STA ICBLL,X LDA #.LOW.MLENH ;LENGTH(HIGH) STA ICBLH,X JSR CIO ;WRITE DATA BLOCK BMI ERRWR ;IF WRITE ERROR THEN JMP JSR CLOSX 3 BMI ERRWR LDY #0 RET RTS ; OREST LDA #.LOW.OPEN STA ICCOM,X LDA #.LOW.NAMEL ;ROUTINE TO COMPLETE OPEN OF 'D1:MEMORY.SAV STA ICBAL,X ;CALLING SUB SUPPLIES 'READ' OR 'WRITE' 4 LDA #.LOW.NAMEH ;IN ICAX1 STA ICBAH,X JMP CIO ; ERRWR STY TEMP+1 ;TEMP STORE FOR Y FLAG JSR CLOSX ;CLOSE #$20 LDA #.LOW.DELETE ;DELETE PART OF MENSAV STA 5 ICCOM,X JSR OREST TEMP LDY #0 ;RESTORE FLAG RTS ;RETURN TO MAIN CALLER .PAGE ; **** ENTRY POINT ON 'DOS' CALL **** ; ; INISAV .DBYTE 0 ;DOSINI VECTOR SAVE LOC6 MEMFLG .BYTE 0 MNDUP LDX #0 STX MEMFLG STX LOADFG DEX STX WARMST JSR INITIO ; JSR MEMSVQ ;FIND OUT IF FILE D1:MEM.SAV EXISTS BPL GOOD ;BRANCH I7F MEM.SAV FILE EXITS LDA #0 STA WARMST ;CLEAR WARM START FLAG BEQ FINAL ; ; GOOD JSR MWRITE ;WRITE USER AREA TO MEM.SAV BMI ERROR DEC MEMFLG ;SHOW MEMORY WRITT8EN BMI FINAL ; ERROR LDA #.LOW.ERRMES ;PRINT ERROR OCCURED MSG LDX #.HIGH.ERRMES JSR PRNTMSG ;GOTO MSG PRINTER ; LDA #.LOW.ERR ;PRINT QUERY TO RUN DOS LDX #.HIGH.ERR 9 JSR PRNTMSG ;GOTO MSG PRINTER ; ; WAIT FOR Y TO RUN DOS ; LDA #GETREC STA ICCOM LDA #.LOW.STAKL STA ICBAL LDA #.LOW.STAKH STA ICBAH LDA #2 :STA ICBLL LDA #0 STA ICBLH JSR CIO LDA STAK ;SEE IF Y TYPED CMP #'Y BNE RTCART ;BRANCH IF NOT LDA #0 STA WARMST ; FINAL LDX #$2;0 LDA #CLOSE STA ICCOM,X ;SET UP CLOSE COMMAND JSR CIO ;PERFORM CLOSE COMMAND ; RRDUP LDA DOSINI ;SAVE DOS INIT VECTOR STA INISAV LDA DOSINI+1 STA < INISAV+1 ; LDA #.LOW.DOS ;SET UP DUP INIT ADDR AS STA DOSINI ;DOS INIT VECTOR LDA #.HIGH.DOS STA DOSINI+1 ; RRDUP1 LDA #.LOW.DUPSYS LDX #$10 STA ICBAL,X = LDA #.HIGH.DUPSYS STA ICBAH,X LDY #0 STY OPT ;ASSURE NO /N OPTION IN EFFECT DEY ;SHOW THAT DUP IS IN MEMORY STY DUPFLG JSR SFLOAD ;LOAD DUP>.SYS AND RUN IT RTCART RTS EC .BYTE 'E:',CR HILO EC HILO MNDUP DUPSYS .BYTE 'D1:DUP.SYS',CR ; ERRMES .BYTE 'ERROR-SAVING USER MEMORY ON DISK',CR ERR .BYTE 'TYPE Y TO STILL RUN DOS',CR .PAGE ; **** SUBR?OUTINES FOR RESIDENT DUP **** ; ; ; ROUTINE TESTS IF MEM.SAV IS PRESENT ON THE DISK. ; RETURNS - MINUS IF NOT THERE ; PLUS IF MEM.SAV IS THERE ; MEMSVQ JSR CLOS20 ;CLOSE IOCB # 2 LDA #OPEN @ STA ICCOM,X LDA #.LOW.NAMEL STA ICBAL,X LDA #.LOW.NAMEH STA ICBAH,X LDA #ORDWRT STA ICAX1,X ;TRY TO OPEN D1:MEM.SAV FOR READ/WRITE JSR CIO PHP A ;SAVE STATUS JSR CLOS20 ;CLOSE MEM.SAV PLP ;RESTORE STATUS RTS ; ; ; SAVE FILE SUBROUTINE - WRITE FILE BODY, INIT, & RUN VECTORS ; WDR1 LDA #0 ;THIS IMMBEDIATE VALUE MODIFIED BEQ WDR2 ;BR IF MEM FILE DOESNT HAVE TO BE LOADED JSR LDMEM WDR2 LDX #$10 JSR CIO ;DO SAVE - WRITE BODY TO DISK INITQ LDA #0 ;THIS IMMED VALUE CHACNGED DURING SAVE BEQ RUNQ ;SET TO FF WHEN AN INIT VECTOR IS PRESNT INC INITQ+1 LDA INITAD STA VECTR ;IF INIT VECTOR FOR FILE SAVE IT LDA INITAD+1 STA VECTR+1 D LDA #.LOW.INITAD TAX STA LDST LDA #.HIGH.INITAD JSR WRVEC RUNQ LDA #0 ;THIS IMMEDIATE VALUE MODIFIED BEQ NORNAD ;SET TO FF WHEN A RUN VECTOR IS PRESENT E INC RUNQ+1 LDA RUNAD STA VECTR ;IF RUN VECTOR FOR FILE SAVE IT LDA RUNAD+1 STA VECTR+1 LDA #.LOW.RUNAD TAX STA LDST LDA #.HIGH.RUNAD JSR F WRVEC NORNAD JSR CLOSX ;CLOSE IOCBS 1 &2 LDA MEMFLG AND WDR1+1 BEQ DRRDUP INC WDR1+1 ;RESET MEM.NEEDS TO BE LOADED FLAG JMP RRDUP1 ;RELOAD & RUN DUP DRRDUP G JMP DOSOS ;RUN THE SWAPPED IN DUP ; ; ; WRVEC STA LDST+1 INX STX LDND STA LDND+1 LDX #$10 LDA #.LOW.LDST STA ICBAL,X LDA #.HIGH.LDST STA ICBHAH,X LDA #6 STA ICBLL,X LDA #0 STA ICBLH,X JMP CIO ;WRITE INIT OR RUN ADDRESS ; ; ; JUMP TO CARTRIDGE ; CLMJMP JSR LDMEM LDA #0 ;SHOW DUP NO LONGIER IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOS INIT VECTOR SAVED JMP (CARTST) ;JUMP TO CARTRIDGE ; ; ; LOAD MEM.SAV (IF IT EXISTS) BEFORE RUN AT ADDRESS ; LMTR JSR LDMEM ;LOAD MJEM.SAVE IF IT EXISTS LDA #0 ;SHOW THAT DUP NO LONGER IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOS INIT VECTOR SAVED JMP (RAMLO) ;RUN AT ADDRESS ; ; RESTORE DOSINI VECTORK FROM SAVED LOCATION ; RELDIN LDA INISAV STA DOSINI LDA INISAV+1 STA DOSINI+1 RTS ; ; ; SUBROUTINE - LDMEM ; LOAD MEM.SAV IF IT EXISTS ; LDMEM LDA MEMFLG BNE LDMEM1 L;BRANCH IF MEMORY WAS SAVED RTS LDMEM1 JSR MEMSVQ BPL LDMEM2 ;BRANCH IF MEM.SAV FILE DOES EXIST LDA #0 ;TELL CART PGM AREA CLOBBERED STA WARMST BEQ CLOS2 ;GO CLMOSE AND GOTO CART ; LDMEM2 LDA #OPEN STA ICCOM,X JSR CIO ;REOPEN MEM.SAV LDA #GETCHR STA ICCOM,X LDA #.LOW.MLENL+1 STA ICBLL,X LDA #.LOW.MLENH SNTA ICBLH,X LDA #.LOW.NDOSL STA ICBAL,X LDA #.LOW.NDOSH STA ICBAH,X JSR CIO CLOS2 LDA #CLOSE STA ICCOM,X JMP CIO ;CLOSE MEM.SAV ; ; CLOSE ALL OIOCBS & RE-OPEN ZERO AS SCREEN EDITOR ; INITIO JSR CIOINV ;THIS ROUTINE CLOSES ALL IOCB'S ;THEN REOPENS THE SCREEN EDITOR LDX #0 LDA #OPEN STA ICCOM,X LDA #.LOPW.ECL STA ICBAL,X LDA #.LOW.ECH STA ICBAH,X LDA #ORDWRT STA ICAX1,X JSR CIO ; LDX #0 ;DELAY UNTIL DMA (SCREEN) IS RESTORED STX CDTMV3 ;QCLEAR TIMER NUMBER 3 STX CDTMV3+1 LDY #1 ;WAIT FOR ONE VBLANK LDA #3 ;USE TIMER # 3 STA CDTMF3 ;SET TIMER DONE FLAG TO NOT DONE JSR SETVBV ;SYSTEM CARLL TO SET TIMER WAITIM LDA CDTMF3 ;WAIT UNTIL TIMER IS DONE BNE WAITIM ; RTS ; ; CLOSX - CLOSE IOCBS 10,20 ; CLOSX LDA #CLOSE LDX #$10 STA ICCOM,X JSR CIO ; ; ENTRY TO CLSOSE IOCB # 2 ONLY ; CLOS20 LDX #$20 LDA #CLOSE STA ICCOM,X JMP CIO ; ; SUBROUTINE - PRNTMSG ; PUTS A CHARACTER STRING TERMINATED BY A CARRIAGE RETURN CHAR TO ; SCREEN EDITOR. ; ; ENTRY - RTEG A : LOW BYTE MSG ADDRESS ; REG X : HI BYTE MSG ADDRESS ; ; PUT PARAMS IN IOCB - USE IOCB 0 FOR SCREEN EDITOR ; PRNTMSG STA ICBAL ;SET MSG ADDR IN IOCB BUFF ADDR STX ICBAH ; ; SET UP REST OF IOCB ; U LDA #$80 ;SET IN BUFFER LENGTH STA ICBLL ;ASSUME 128 BYTES MAX LDX #0 ;USE REG X TO SET IN IOCB INDEX FOR CIO STX ICBLH LDA #PUTREC ;PUT MSG STAV ICCOM ; ; TEST IF DUP IS RESIDENT - IF IS THEN USE INDIRECT CIO ROUTINE ; TO TEST FOR BREAK KEY ABORT ; LDA DUPFLG ;=ZERO IF NON-RESIDENT DUP NOT IN MEM BNE INMEM ;IN MEMORY THEN USE INDIRECT CWIO CALL ; JMP CIO ;ELSE GO DIRECT TO CIO & RETURN ; INMEM JMP CIO1 ;USE CIO CALL WITH TEST FOR BREAK KEY ABORT ; ; SAVH .BYTE $FF,$FF HILO SAVH LDST: .RES 2 HILO LDST LDND: .RES X 2 VECTR: .RES 2 .PAGE ; **** SIO INTERRUPT SERVICE ROUTINES **** ; ; ; EQUATES FOR INTERRUPT ROUTINES MOVED FROM SIO ; ; ZERO PAGE ; BUFRLO = $32 ;POINTER TO BYTE TO SEND OR RECEIVE BUFRHI = $33Y BFENLO = $34 ;POINTER TO BYTE AFTER END OF BUFFER BFENHI = $35 CHKSUM = $31 ;LOC TO STORE DATA FRAME CHECKSUM CHKSNT = $3B ;CHECKSUM SENT FLAG- =FF SENT NOCKSM = $3C ;FLZAG NO CHECK SUM TO BE RECEIVED-NOT ZERO STATUS = $30 ;HOLD FOR STATUS TO BE PUT IN DCB BUFRFL = $38 ;FLAG-IF FF RECEIVE BUFFER IS FULL RECVDN = $39 ;FLAG RECEIVE NOT DONE. USED BY WAIT LOOP POKMSK[ = $10 ;POKEY INTERRUPT MASK SHADOW FOR IRQEN ; ; HARDWARE REGISTERS USED IN SIO INTERRUPT ROUTINES ; SKRES = $D20A ;SERIAL PORT STATUS RESET ON POKEY SEROUT = $D20D ;SERIAL OUTPUT REGISTER SER\IN = SEROUT ;SERIAL PORT INPUT REG ON POKEY IRQEN = $D20E ;IRQ INTERRUPT ENABLE ON POKEY SKSTAT = $D20F ;SERIAL PORT STATUS REG ON POKEY ; ; ERROR CODES RETURNED BY SIO ; FRMERR = $8C ] ;FRAMING ERROR ON INPUT OVRRUN = $8E ;DATA FRAME OVER RUN-BIT D5 IN SKSTAT CHKERR = $8F ;DATA FRAME CHECKSUM ERROR .PAGE ; **** INTERRUPT SERVICE ROUTINE TO OUTPUT DATA NEEDED **** ; ; ; ; ^ IT UPDATES THE BYTE TO PUT ON SERIAL I/O BUS POINTER ; UNTIL END OF BUFFER. AFTER EACH UPDATE OF THE PTR ADDS THE ; VALUE OF THE BYTE TO THE CHECKSUM. OUTPUTS THE CHECKSUM WHEN ; PTR EQUALS THE END OF BUFFER PTR (POINTS TO BYTE _AFTER BUFFER). ; RETURNS TO THIS ROUTINE AFTER CHECKSUM PASSED AND RESETS POKEY ; INTERRUPT REG TO HAVE THE TRANSMIT DONE ROUTINE CALLED TO END ; WAIT LOOP (SEE SIO LISTING). ; ; K.B. 6/10/80 ; ISRODN TYA ;SA`VE Y REG ON STACK PHA ; INC BUFRLO BNE NOWRP0 ;INCREMENT PTR TO NEXT BYTE INC BUFRHI ;TO SEND ; ; PATCH TO ROUTINE - CHANGED CHECK ; NOWRP0 LDA BUFRLO ;CHECK IF PTR IS WITaHIN BUFFER CMP BFENLO ;DO A DOUBLE PRECISION SUBTRACT LDA BUFRHI SBC BFENHI BCC NOTEND ;BRANCH IF (BUFR) < (BFEN)-MORE TO SEND ; LDA CHKSNT ;TEST IF CHECKSUM ALREADY bSENT BNE RELONE ;BRANCH IF ALREADY SENT ; ; SEND CHECKSUM AND SET FLAG ; LDA CHKSUM STA SEROUT ;PUT CHECKSUM IN SERIAL OUT REG DEC CHKSNT ;SET FLAG TO FF HEX BNE c CHKDON ;RETURN ; ; AFTER CHECKSUM SENT AND CAUSE NEXT INTERRUPT THEN CHANGE POKEY ; MASK TO ENABLE TRANSMIT DONE INTERRUPT AND TERMINATE WAIT LOOP. ; RELONE LDA POKMSK ;GET POKEY MASK ORA #$08 d;OR IN ENABLE STA POKMSK STA IRQEN ;ENABLE THE INTERRUPTS ; ; RESTORE REGS AND RETURN ; CHKDON PLA TAY ;RESTORE Y REG PLA ;RESTORE A REG SAVED IN OS IRQ INTeERRUPT HANDLER RTI ; ; MORE TO SEND. SEND NEXT BYTE POINTED AT BY BUFR. ; NOTEND LDY #0 LDA (BUFRLO),Y ;GET NEXT BYTE STA SEROUT ;PUT IN SERIAL OUT REG ; CLC ADC CHKSUM f ;ADD BYTE TO CHECKSUM ADC #0 STA CHKSUM ; JMP CHKDON ;GO RETURN AND WAIT FOR NEXT BYTE ; ; ******** END OF OUT SERVICE ROUTINE ******** .PAGE ; **** SERIAL INPUT READY INTERRUPT SERVICgE ROUTINE **** ; ; ; ; AFTER SERIAL RECEIVE IS ENABLED ROUTINE IS USED TO COLLECT ; BYTES FROM THE SERIAL INPUT REG AND PUT THEM IN BUFFER. ; WILL STOP WHEN BUFFER IS FULL. IF A CHECKSUM IS EXPECTED ; ROUTINE WILL MARK BUFFER hFULL AND CONTINUE. WHEN CHECKSUM ; RECEIVED IT WILL CHECK IF = TO CHECKSUM IT WAS MAKING. ; WILL STORE ERRORS FOUND IN STATUS LOCATION. ; ; THE IRQ INTERRUPT HANDLER IN THE OS PUSHES THE USER'S A REGISTER ; ONTO THE STACK BEFORE iCALLING THIS ROUTINE. ; ; K.B. 6/11/80 ; ISRSIR TYA ;SAVE Y REG ON STACK PHA ; ; GET STATUS FROM POKEY THEN RESET IT. ; LDA SKSTAT STA SKRES ;IGNORES VALUE- JUST STROBED ; ; j CHECK FOR ERRORS ; BMI NTFRAM ;BIT 8 SET IF NO FRAMING ERROR LDY #FRMERR STY STATUS ;SET FRAME ERROR STATUS ; NTFRAM AND #$20 ;IF BIT 5 CLEAR THEN FRAME OVER RUN BNE NkTOVRN ;BRANCH IF NO OVER RUN LDY #OVRRUN STY STATUS ;ELSE SET OVERRUN ERROR STATUS ; ; CHECK IF BUFFER FULL AND THIS IS A CHECKSUM. IF IT IS, THEN ; CHECK IF DATA SENT WAS VALID. ; NTOVRN LDA BlUFRFL ;TEST FOR BUFFER FULL (NOT ZERO) BEQ NOTYET ;IF ZERO THEN NOT YET, THIS IS DATA. LDA SERIN ;ELSE THIS IS CHECKSUM CMP CHKSUM ;ARE THEY EQUAL? BEQ SRETRN m;YES,THEN RETURN LDY #CHKERR ;ELSE SET CHECK SUM ERROR STATUS STY STATUS ; ; SET RECEIVE DONE TO END WAIT LOOP ; SRETRN LDA #$FF ;DONE VALUE STA RECVDN ; ; RESTORE REGS AND RETURN ;n SUSUAL PLA TAY ;RESTORE Y REG PLA ;RESTORE A REG RTI ; ; IF BYTE IS DATA, THEN GET HERE. PUT BYTE IN BUFFER AND CHECK IF ; AT END OF BUFFER. ; NOTYET LDA SERIN o ;GET DATA BYTE LDY #0 STA (BUFRLO),Y ;STORE IT IN THE BUFFER ; CLC ADC CHKSUM ;ADD DATA BYTE TO CHECKSUM ADC #0 STA CHKSUM ; INC BUFRLO ;INCREMENT POpINTER TO LOCATION BNE NTWRP1 ;FOR NEXT BYTE INPUT INC BUFRHI ; ; THE PATCH CHANGED THE TEST FOR END OF BUFFER ; NTWRP1 LDA BUFRLO ;DO DOUBLE PRECISION SUBTRACT CMP BFENLO LDA qBUFRHI SBC BFENHI ;CARRY CLEAR IF BORROW BCC SUSUAL ;BRANCH IF (BUFR) < (BFEN)-WITHIN BUFFER LIMIT ; ; DONE WITH DATA. SEE IF CHECKSUM TO BE SENT ; LDA NOCKSM ;IF = ZERO THEN A CHECKSrUM BEQ GOON ;WILL FOLLOW THE DATA ; LDA #0 ;ELSE NO CHECKSUM TO FOLLOW STA NOCKSM ;CLEAR NO CHECKSUM FLAG BEQ SRETRN ;RETURN AFTER SET RECEIVE DONE FLAG ; ; sSET BUFFER FULL AND THEN GO GET CHECKSUM ; GOON DEC BUFRFL ;SET BUFFER FULL FLAG TO FF BNE SUSUAL ;GO RETURN ; ; ******** END OF RECEIVE SERIAL INPUT INTERRUPT ROUTINE ******** MDEND = * HILO t MDEND *= $70C .BYTE MDENDL,MDENDH ;SET END ADDR IN FMS PAST RES DUP SO ; ;BUFFERS DON'T CLOBBER IT. STAK = $100 HILO STAK .PAGE ; ******** BEGINNING OF NON-RESIDENT u PORTION OF DUP ******** ; ; NDOS = MDEND+$300 ;END OF THE SYSTEM BUFFERS AND MINIDUP HILO NDOS *= NDOS PAR: .RES 40 ;PARAMETER AREA PARH = PAR/256 PARL = (-256)*PARH+PAR LINvE: .RES 80 ;TYPE IN LINE BUFFER LBUFH = LINE/256 LBUFL = (-256)*LBUFH+LINE DBUF: .RES $100 ;DATA BUFFER FOR COPY DB1 = DBUF+$80 DB3 = DBUF-3 HILO DBUF HILO DB1 w HILO DB3 DBLL = 0 DBLH = 1 ;DATA BUFFER LENGTH=$100 EDBLL = $FA ;DATA BUFFER LENGTH USED IN USEPGM EDBLH = 0 ;MUST BE A MULTIPLE OF 125, SECTOR DATA LENGTH MENUSZ: .RES x 1 PER: .RES 1 UNNO: .RES 1 RCNT: .RES 1 SSTAT: .RES 1 SWDP: .RES 5 CSRC: .RES 1 CDES: .RES 1 SAVX: .RES 1 PTR: .RES 1 IPTR: .RES 1 CTR: .RES 1 T1: .RES 2 BUFLEN = T1 y;SAVE AREA FOR BUFR LEN, USED IN USEPGM STVEC: .RES 2 ;A TEMP OF SOME KIND MLT125 = STVEC ;TEMP STORE FOR MULTIPLE OF 125, USEPGM SECSIZ: .RES 2 ;TO STORE SECT SIZE IN BYTES FOR DUP DSK EOFFLG: .RES z 1 ;ENDFILE FLAG FOR SOURCE IN DUPFIL FTRF: .RES 1 ;FIRST TIME READ FLAG USED IN DUPFIL TWODRV = FTRF ;FLAG TO SHOW IF 1 OR 2 DRIVES. USED IN DUPDISK DTH =* HILO DTH EDN .BYTE 'E:',{CR EDH = EDN/256 EDL = (-256)*EDH+EDN .PAGE ; **** DOS MENU **** ; ; DMENU .BYTE CLSCR .BYTE 'DISK OPERATING SYSTEM II VERSION 2.0S',CR .BYTE 'COPYRIGHT 1980 ATARI',CR,CR .BYTE 'A. DISK D|IRECTORY I. FORMAT DISK',CR .BYTE 'B. RUN CARTRIDGE J. DUPLICATE DISK',CR .PAGE .BYTE 'C. COPY FILE K. BINARY SAVE',CR .BYTE 'D. DELETE FILE(S) L. BINARY LOAD',CR .BYTE 'E. RENAME FILE M. RUN AT A}DDRESS',CR .BYTE 'F. LOCK FILE N. CREATE MEM.SAV',CR .PAGE .BYTE 'G. UNLOCK FILE O. DUPLICATE FILE',CR .BYTE 'H. WRITE DOS FILES',CR .BYTE CDN,CDN,CDN,CDN,CDN DMEND =* DULEN = DMEND-DMENU~ HILO DULEN HILO DMENU ; DUJPT .WORD DIRLST,STCAR,CPYFIL,DELFIL,RENFIL,LKFIL,ULFIL .WORD WBOOT,FMTDSK,DUPDSK,SAVFIL,LDFIL,BRUN,MEMSAV .WORD DUPFIL HILO DUJPT DUNUM = 15 ;NUMBER OF FUNCTIONS .PAGE ; **** DISK OPERATING SYS MONITOR **** ; ; DOSOS LDX #$FF HILO DOSOS CLD ;MAKE SURE DECIMAL MODE OFF STX BRKKEY INX STX LOADFG LDA  #2 STA LMARGN LDA #39 STA RMARGN ;SET MARGINS LDA POKMSK ;ENABLE BREAK INTERRRUPTS ORA #$80 STA POKMSK STA IRQEN JSR INITIO ;CLOSE FILES ; ; DISK UTILITY MONITOR ; DSKUTL DU1 LDA #DUNUM STA MENUSZ ;SET MENU SIZE LDA #.LOW.DUJPTL STA JMPTBL LDA #.LOW.DUJPTH STA JMPTBL+1 ;SET UP JUMP TABLE ADDRESS ; FALL THRU TO MENU SELECT ; ; ; ; MENU SELECT MONITOR -- VECTORS TO ROUTINE SELECTED FROM MENU. ; SHMEN LDA #.LOW.DMENUL ;GET MENU ADDRESS STA ICBAL LDA #.LOW.DMENUH STA ICBAH LDA #.LOW.DULENL ;GET MENU LENGTH STA ICBLL LDA #.LOW.DULENH STA ICBLH JSR DSPMSG ;SHOW MENU ; ; SELECT ITEM FROM MENU .PAGE ; **** FUNCTIONS COME HERE WHEN THEY ARE DONE **** ; MENUSL LDX #$FF ;RESET STACK AT THIS POINT TXS INX STX WCFLAG ;CLEAR WILD-CARD FLAG LDA #.LOW.SITL ;SELECT ITEM MESSAGE LDX #.LOW.SITH JSR PRNTMSG LDA #$40  ;MAKE SURE UPPER CASE STA SHFLOK JSR CHRGET ;GO GET KEYBOARD CHAR. ; CMP #CR ;IF CR RE-DISPLAY MENU BEQ SHMEN ; SEC SBC #'A ;CONVRT ASCII CHAR. TO BINARY # & SUB. 1 BMI RANGE ;IF ASCII CHAR NOT A #, GO READ AGAIN CMP MENUSZ ;IS THE # ENTERED > MENU SIZE? BPL RANGE ;IF YES, GO READ AGAIN. ASL A TAY  ;SET INDEX TO (MENU # - 1) * 2 LDA (JMPTBL),Y INY STA RAMLO ;GET STRING POINTER LDA (JMPTBL),Y STA RAMLO+1 LDY #1 ;LOAD STRING POINTER INTO REGISTERS  LDA (RAMLO),Y ;FOR DSPLIN TAX DEY LDA (RAMLO),Y JSR DSPLIN ;PRINT MODULES INITIAL STRING JSR SCROL ;SCROLL INPUT WINDOW LDA RAMLO ;INC BY 2 TO POINT PAST STRING POINTER CLC ADC #2 STA RAMLO LDA RAMLO+1 ADC #0 ;CARRY STA RAMLO+1 ;PUT HI BYTE. JMP (RAMLO) ;JUMP TO ROUTINE SELECTED BY MENU. RANGE LDA #.LOW.NSIL LDX #.LOW.NSIH JSR DSPLIN ;NO SUCH ITEM MESSAGE JMP MENUSL .PAGE NSI .BYTE 'NO SUCH ITEM',CR ; ;PROMPT FOR MENU SELECTION OR REDISPLAY MENU - RETURN IS IN INVERSE ; SIT .BYTE 'SELECT ITEM OR ',$D2,$C5,$D4,$D5,$D2,$CE .BYTE ' FOR MENU',CR HILO NSI HILO SIT MNSL = MENUSL HILO MNSL .PAGE ; **** DIRECTORY LISTING ROUTINE **** ; ; DIRLST .WORD DLMG  JSR GETIC1 JSR USEBUF ;INIT BUFADR & BUFLEN LDX PTR LDA #CR STA PAR-1,X ;ASSURE GOOD TERM LDA PAR-2,X ;LAST CHAR OF SEARCH SPEC CMP #':  ;IF COLON, ADD *.* BNE GLF LDA #'* STA PAR-1,X STA PAR+1,X LDA #'. STA PAR,X LDA #CR STA PAR+2,X INX INX INX STX PTR GLF STX SAVX LDX #$20 JSR PIOCB JSR GETFIL JSR PERX LDA #6 ;READ DIR INFO LDX #$10 STA ICAX1,X LDA #OPEN ;OPEN STA ICCOM,X STX CSRC ;COPY SOURCE=DIRECTORY INFO CPX #$10 BNE *+3 JSR CIOCL LDA PTR SEC SBC SAVX CMP #3 ;IF ONLY 3 CHARS, IS 'D:'CR, USE DEFAULT BEQ DLST1 DLST0 JMP PDES ;GO INTO COPY DLST1 LDX SAVX LDA PAR,X CMP #'D BNE DLST0 JMP PDES1 ;GO INTO COPY WITH DES='E:' .PAGE DLMG .BYTE 'DIRECTORY--SEARCH SPEC,LIST FILE?',CR .PAGE ; **** DELETE FILE ROUTINE **** ; ; DELFIL .WORD DEMG JSR GETIC1 JSR PERX ;EXIT IF PARAM ERRORS ; JSR CHKVER ;BE SURE THAT IT IS VER. 2 DISKETTE ; ; CONTINUE WITH DELETE - ALLOW ONLY FOR DISK DEVICE ID ; LDA PAR ;GET DEVICE CMP #'D ;ONLY ALLOW DELETE FOR D: BEQ DF1 LDA #.LOW.NDFL LDX #.LOW.NDFH JSR DSPLIN JMP MENUSL NDF .BYTE 'NOT A DISK FILE',CR HILO NDF DF1 LDX #$10 LDA OPT CMP #'N ;IF OPTION=N, NO QUERY BNE DWQ ;NO, DELETE WITH QUERY LDA #DELETE STA ICCOM,X JSR CIOCL JMP MENUSL DWQ LDA #.LOW.TYQL LDX #.LOW.TYQH JSR DSPLIN ;SAY TYPE Y TO DELETE... LDA #0 STA IPTR ;HOW MANY FILES TO SKIP, NONE AT FIRST LDX #$20 ;SET UP DELETE IOCB LDA #DELETE STA ICCOM,X LDA #.LOW.DB3L STA ICBAL,X LDA #.LOW.DB3H STA ICBAH,X LDA #'D STA DBUF-3 LDA #': STA DBUF-1 LDA PAR+1 ;DEVICE NUMBER OR : FROM OP INPUT CMP #': BNE *+4 LDA #'1 STA DBUF-2 ;KLUDGE KLUDGE KLUDGE IDRD  LDX #$10 LDA #OPEN STA ICCOM,X LDA #6 STA ICAX1,X ;DIR READ OPEN LDA #PARL STA ICBAL,X LDA #PARH STA ICBAH,X JSR CIOCL LDA #.LOW.DBUFL STA ICBAL,X LDA #.LOW.DBUFH STA ICBAH,X LDA #GETREC STA ICCOM,X LDA #0 STA PTR ;HOW MANY FILES WE HAVE SKIPPED ; ; READ FILENAME FROM DIR, QUERY AND DELETE ; RDFN LDX #$10 LDA #0 STA ICBLL,X LDA #1 STA ICBLH,X JSR CIOCL ;READ A LINE FROM DIRECTORY LDA DBUF+1 ;IF FILE LINE, THIS IS BLANK  CMP #' BNE DELX ;THIS IS FREE BLOCKS LINE INC PTR ;COUNT THIS FILE LDA PTR ;HAVE WE SKIPPED ENUF YET CMP IPTR BMI RDFN ;BR IF NO LDX  #0 ;PUT PTR LDY #2 ;GET PTR ; ; MESSAGE DELETE FILE NAMES ; MDN1 LDA DBUF,Y CMP #' ;END OF FILENAME BEQ MDN2 STA DBUF,X INX INY CPX  #8 BMI MDN1 ; ; FILENAME IS MOVED, PUT .EXT ; MDN2 LDA #'. STA DBUF,X INX LDY #10 ;WHERE EXT IS MDN3 LDA DBUF,Y STA DBUF,X INY INX CPY #13  BMI MDN3 STX SAVX ;PUT CR HERE LATER LDA #'? ;FOR QUERY STA DBUF,X INX LDA #CR STA DBUF,X LDA #.LOW.DB3L LDX #.LOW.DB3H  JSR DSPLIN ;GO ASK ABOUT THIS FILE JSR CHRGET CMP #'Y BNE RDFN ;GO DO NEXT FILENAME LDA PTR ;NUMBER FILES WE HAVE GONE THRU SO FAR STA IPTR ;IS NEW NUMBER TO SKIP. LDX SAVX LDA #CR STA DBUF,X LDX #$20 ;DELETE IOCB JSR CIOCL JSR CLOS1 JMP IDRD ;CLOSE AND REOPEN DIR READ FILE DELX JSR CLOS1 ;CLOSE DIR READ FILE JMP MENUSL CLOS1 LDX #$10 LDA #CLOSE STA ICCOM,X JMP CIOCL ;DO CLOSE AND RETURN TYQ .BYTE 'TYPE ',$22,'Y',$22,' TO DELETE...',CR HILO TYQ DEMG .BYTE 'DELETE FILE SPEC',CR ;LIST .PAGE ; **** COPY FILE ROUTINE **** ; ; CPMG .BYTE 'COPY--FROM, TO?',CR OE .BYTE 'OPTION NOT ALLOWED',CR HILO OE ; ; ; ; ; WCFLAG: .RES 1 WCSKP1: .RES 1 WCSKP2: .RES  1 WCBUFL = 20 WCBUF: .RES WCBUFL WCOPYM .BYTE ' COPYING---' WCBUF2 .BYTE 'DN:' .RES WCBUFL-3 CPYFIL .WORD CPMG ;COPY FILE PROMPT JSR GETIC1 ;GET SOURCE DEVICE, ETC. LDA PTR  STA SAVX LDA PAR ;GET 1ST CHAR. OF DEVICE CMP #'D ;TEST IF IT IS THE DISK BNE JMPNWC ;BR IF NOT THE DISK (THEN USE OLD CODE) LDX #0 ;LOOK AT SOURCE FILE SPEC. JSR LOOKWC ;LOOK FOR WILDCARDS IN FILE SPEC. BEQ CPYFL1 ;BRANCH IF WILDCARDS USED IN DISK SPEC. JMPNWC JMP NOTWC ;USE OLD CODE CPYFL1 LDA #$80 ; ; WCINIT STA WCFLAG ;'WLDCARD' MODE (COPY-FILE OR DUP-FIL LDA #0 STA WCSKP1 ; WCOPYL LDA #0 STA WCSKP2 LDX #$10 ;OPEN DIRECTORY LDA #6 STA ICAX1,X LDA #OPEN STA ICCOM,X LDA #.LOW.PAR STA ICBAL,X LDA #.HIGH.PAR STA ICBAH,X JSR CIOCL ; ; WCOPYR LDA #GETREC ;READ DIRECTORY STA ICCOM,X LDA #WCBUFL STA ICBLL,X LDA #0 STA ICBLH,X LDA #.LOW.WCBUF STA ICBAL,X LDA #.HIGH.WCBUF STA ICBAH,X JSR CIOCL ; LDA WCBUF ;IF 1ST CHAR. OF DIR READ IS A #-IT IS T  CMP #'0 BCC WCGOT CMP #': BCS WCGOT ; LDA #CLOSE ;ALL DONE -- NORM EXIT OF WILDCARD COPY STA ICCOM,X JSR CIOCL JMP MENUSL ; ; WCGOT LDA WCSKP1  ;IF ALREADY COPIED OR SKIPPED THIS FILE CMP WCSKP2 BEQ SKIP1 ; INC WCSKP2 BNE WCOPYR ; SKIP1 INC WCSKP1 ; LDA #CLOSE ;CLOSE DIRECTORY READ FILE STA ICCOM,X  JSR CIOCL ; ; LDY #2 ;DON'T COPY .SYS FILES SYSLOP LDA WCBUF+10,Y CMP DOTSYS,Y BNE NOSYS DEY BPL SYSLOP BMI WCOPYL ; DOTSYS .BYTE 'SYS' ; NOSYS LDY #'1 ;CALC SOURCE DRIVE NUMBER LDA PAR+1 CMP #': BEQ WCGOT1 TAY WCGOT1 STY WCBUF2+1 ; ; LDX #2 ;COMPRESS SPACES, ADD ':', ADD 'CR' LDY #3 ; COMPR1 LDA WCBUF,X CMP #' BEQ COMPR2 STA WCBUF2,Y INY ; COMPR2 INX CPX #10 BNE COMPR1 ; LDA WCBUF,X CMP #' BEQ COMPR5 LDA #'. STA WCBUF2,Y INY COMPR3 LDA WCBUF,X CMP #' BEQ COMPR4 STA WCBUF2,Y INY COMPR4 INX CPX #13 BNE COMPR3 ; COMPR5 LDA #CR STA WCBUF2,Y ; ; LDA #.LOW.WCOPYM  ;PRINT 'COPYING---DEV:FILENAME.EXT' MSG LDX #.HIGH.WCOPYM JSR DSPLIN ; BIT WCFLAG BVC WCOPY ;BR TO MIDDLE OF DUP FILE ROUTINE IF DU ; LDX #$10 ;SET UP BUFR ADDR TO PNT TO WLDCARD FIL LDA #.LOW.WCBUF2 STA ICBAL,X LDA #.HIGH.WCBUF2 STA ICBAH,X JMP WCDUPS ; WCOPY JSR USEPGM ;SET BUFFER SIZES LDX #$10 ;OPEN COPY SOURCE FILE  LDA #OPEN STA ICCOM,X LDA #4 STA ICAX1,X LDA #.LOW.WCBUF2 STA ICBAL,X LDA #.HIGH.WCBUF2 STA ICBAH,X STX CSRC JSR CIOCL ; LDX  #$20 JSR PIOCB ;GET COPY DESTINATION FILE LDA PTR ;SAVE PTR,IPTR- MIGHT REPET GETTING 2ND MES PHA LDA IPTR PHA JSR GETFIL ;GET 2ND FILE NAME TO PAR PLA ;RECOVER IPTR,PTR STA IPTR PLA STA PTR LDX SAVX LDA PAR,X CMP #'D BEQ WCOPY0 JMP PDES ;JMP TO OLD CPY-FILE CODE IF NOT DSK DEST ; WCOPY0 LDY #'1 ;CALCULATE DESTINATION DRIVE # LDA PAR+1,X CMP #': BEQ WCOPY1 ; TAY WCOPY1 CPY WCBUF2+1 BNE WCOPY2 JSR CLOSX ;CANT COPY TO SAME DRVE NMBR - ERR & EXI ; JMP ODMS ; ; WCOPY2 LDX #$20 STY WCBUF2+1 ;CHANGE FILESPEC TO DESTINATION LDA #.LOW.WCBUF2 STA ICBAL,X LDA #.HIGH.WCBUF2 STA ICBAH,X JMP OPDES1 ;CONTINUE INTO OLD COPY-FILE CODE ; ; NOTWC = * LDX #$20 ;IOCB 3 JSR PIOCB JSR GETFIL ;GET SECOND FILENAME ; ; MAKE SURE DESTINATION IS NOT DOS.SYS ; LDX SAVX ;ENTRY-INDEX TO DEST FILE SPEC JSR TSTDOS ;WON'T RETURN IF IS DOS.SYS ; LDX SAVX JSR LOOKWC BNE NWCIND ;BRANCH IF NO WILDCARDS IN DESTINATION LDA #.LOW.NWAL  LDX #.LOW.NWAH JSR DSPLIN JMP MENUSL NWA .BYTE 'WILD CARDS NOT ALLOWED IN DESTINATION',CR HILO NWA NWCIND = * JSR PERX ;IF PARAM ERRS, EXIT JSR USEPGM ;ASK USR IF CAN USE PGM AREA OR DATA BFR PSRC = * LDA PAR ;GET 1ST LETR OF PARAM CMP #'K BEQ ODMS ;K:GETS 'OPTION DOESNT MAKE SENSE' FOR NOW CMP #'C BEQ ODMS  ;C: GETS 'OPTION DOESNOT MAKE SENSE' FOR NOW CMP #'E ;E: AS SOURCE IS SPECIAL BNE OPSRC ;IF NO THEN OPEN SOURCE FILE LDX #0 STX CSRC JMP PDES OPSRC CMP #'S  BEQ ODMS ;S: AS SOURCE GETS O.D.M.S. FOR NOW ; ; OPEN SOURCE FILE ; LDX #$10 LDA #OPEN STA ICCOM,X LDA #4 ;OPEN IN STA ICAX1,X STX CSRC  CPX #$10 BNE *+33 JSR CIOCL ;OPEN SOURCE FILE HERE ; ; READY FOR OPEN OF DESTINATION ; PDES LDX SAVX LDA PAR,X ; CMP #'K ;IS DEST KEYBOARD? BEQ ODMS  ;YES, THEN CAN'T DO IT ; CMP #'E ;CHECK FOR SPECIAL CASE BNE OPDES ;IF NOT PDES1 LDA #0 ;SPECIAL CASE - DONT OPEN, USE EXISTING IOCB STA CDES JMP DOCPY ODMS  LDA #OEL LDX #OEH ;SAY OPTION NOT ALLOWED JSR DSPLIN JSR CLOSX ;CLOSE IOCB 1 & 2 JMP MENUSL ; OPDES CMP #'C BEQ ODMS ;C: GETS 'OPTION DOESNOT MAKE SENSE' FOR NOW LDX OPT ;GET 2ND FILE OPTION ; CPX #'A ;APPEND TO DISK FILE BNE OPDES1 CMP #'D BNE ODMS LDA #9 BNE OPDES3 OPDES1 LDA #8 OPDES3 LDX #$20 STA ICAX1,X ;OPEN TYPE OUT LDA #OPEN STA ICCOM,X OPEN STX CDES JSR CIOCL LDA #0 STA ICAX2,X ; ;COPY FROM CSRC TO CDES ; DOCPY LDA #GETCHR GC1 LDX CSRC LDY CDES STA ICCOM,X LDA #PUTCHR STA ICCOM,Y LDA BUFADR ;ADDRESS OF BUFFER - EITHER STA ICBAL,X ;PGM AREA (MEMLO) OR DATA BUFFER (DBUF) STA ICBAL,Y LDA BUFADR+1 ;BUFADR IN LSB,MSB ORDER STA ICBAH,X STA ICBAH,Y CLOOP LDX CSRC LDA BUFLEN ;LENGTH OF BUFFER ADDRESSED STA ICBLL,X ;BY BUFADR LDA BUFLEN+1 ;BOTH BUFADR & BUFLEN ARE ASSIGNED STA ICBLH,X ;IN SUBROUTINE USEPGM JSR CIO ;READ FROM INPUT STY SSTAT LDX CDES LDY CSRC LDA ICBLL,Y  STA ICBLL,X LDA ICBLH,Y STA ICBLH,X ORA ICBLL,Y ;IF SOURCE FILE LENGTH = 0 BEQ CKRS ;DON'T DO WRITE JSR CIOCL ;WRITE, ABORT IF ERROR CKRS LDA SSTAT  ;GET READ OPERATION STATUS BACK BPL CLOOP ;IF OK, GO READ SOME MORE CMP #$88 ;EOF STATUS BEQ *+5 JMP CIOER ;IF NOT, ABORT CLOC LDX CSRC BEQ DU4  ;IF E:, DONT CLOSE ; ;CLOSE SOURCE FILE ; LDA #CLOSE STA ICCOM,X JSR CIO DU4 LDX CDES BEQ DU3 ;IF DES=E: LDA #CLOSE STA ICCOM,X JSR CIO DU3 LDX CDES BNE DU6 LDA #.LOW.DDSK+1 LDX #.HIGH.(DDSK+1) JSR PRNTMSG ;PRNT A CR BEFOR SELECT OR WLDCARD PRMPT DU6 = * ; BIT WCFLAG BPL DU5 JMP WCOPYL ;BRANCH BACK TO WILD CARD LOOP DU5 JMP MENUSL .PAGE ; **** RENAME FILE ROUTINE **** ; ; ;RENAME SETS UP IOCB #1 WITH THE OLD FILE NAME AND THE BUFFER ADDRESS ;POINTS TO THE NEW FILE NAME. THE NEW FILE SPECIFICATION CANNOT HAVE ;A DEVICE ID. THE DEVICE ID IS THE SAME AS SPECIFIED FOR THE OLD FILE ;D2:ABC.S2,QQQ.R3 THIS RENAMES ABC.S2 ON DRIVE #2 TO QQQ.R3 ; RENFIL .WORD RNMG JSR GETIC1 ;GET OLD FILE SPEC & PUT ADDR IN IOCB JSR  GETNAME ;GET NEW FILE NAME JSR PERX ;EXIT IF PARAMETER ERRORS ; JSR CHKVER ;MAKE SURE VER 2 DISKETTE ; ; CONTINUE WITH RENAME ; LDA #RENAME LDX #$10 STA ICCOM,X JSR CIOCL JMP MENUSL RNMG .BYTE 'RENAME - GIVE OLD NAME, NEW',CR ; ;******************* SUBROUTINE ******************* ; ; MAKE SURE THIS IS A VERSION 2 FORMAT DISK ; CHKVER LDY #1 ;ASSUME DRIVE 1- GET DRIVE # LDA PAR+1 ;TEST CHAR 2 OF FILE SPEC FOR SEMICOLON CMP #': ;IF IS, USING DEFAULT DRIVE (1) BEQ DRV1 ;IT IS, SO SAVE DRIVE # AND #$0F ;ELSE CHAR 2 IS ASCII REP OF DRIVE # TAY ;CONVERT TO BINARY & SAVE IT DRV1 STY UNNO ;SAVE DRIVE # ; JMP TSTVER2 ;TST FOR VERS. 2 DISK- WONT RTURN IF NOT ; .PAGE ; **** FORMAT DISK ROUTINE **** ; ; FMTDSK .WORD WHD JSR GETLIN JSR GETDN CLC ADC #'0 STA DDSK STA CDSK JSR PERX LDA #.LOW.VFML ;QUERY TO VERIFY DRIVE NUMBER LDX #.LOW.VFMH JSR DSPLIN JSR CHRGET CMP #'Y ;SEE IF OK BNE FMX LDA #.LOW.FDPL LDX #$10 STA ICBAL,X LDA #.LOW.FDPH STA ICBAH,X LDA  #FORMAT STA ICCOM,X JSR CIOCL ;CALL CIO TO DO FORMAT FMX JMP MENUSL ;EXIT. WHD .BYTE 'WHICH DRIVE TO FORMAT?',CR VFM .BYTE 'TYPE ',$22,'Y',$22,' TO FORMAT DISK ' DDSK: .RES 1 .BYTE CR FDP .BYTE 'D' CDSK: .RES 1 .BYTE ':',CR HILO WHD HILO VFM HILO FDP .PAGE ; **** START CARTRIDGE ROUTINE **** ; ; SYVBL = SYSVBV HILO SYVBL XTVBL = XITVBV HILO XTVBL STCAR .WORD SCMG ;NO MSG, PRINT A ROMTST = $BFFD LDY ROMTST ;TEST IF RAM OR OTHER LDA #$AA ;PATTERN #1 STA ROMTST CMP ROMTST  BNE NOTRAM ;BRANCH IF NOT RAM LDA #$55 ;PATTERN #2 STA ROMTST CMP ROMTST BNE NOTRAM ;BRANCH IF NOT RAM ; STY ROMTST ;THERE IS VALID RAM - SAY NO CART NOCART LDA #.LOW.NCAL LDX #.LOW.NCAH ;SAY NO CART JSR DSPLIN JMP MENUSL ; ; CHECK IF ROM OR EMPTY ADDRESS SPACE ; NOTRAM LDA $BFFC ;KNOWN ROM ZERO BYTE BNE NOCART ;BRANCH IF EMPTY ADDRESS SPACE ; TAX ;SINCE EMPTY ADDR SPACE GIVES A RANDOM CKCART LDA ROMTST ;VALUE, TEST THE SAME LOC MANY TIMES. BEQ NOCART ;BRANCH IF NO CARTRIDGE CMP ROMTST  BNE NOCART ;BRANCH IF NO CARTRIDGE INX BNE CKCART ;LOOP BACK ; ; ; RESET VERTICAL BLANK VECTORS BEFORE ENTERING CART ; JSR INITIO LDA #6 ;SET VVBLKI LDX #.LOW.SYVBLH ;HI BYTE LDY #.LOW.SYVBLL JSR SETVBV LDA #7 ;SET VVBLKD LDX #.LOW.XTVBLH LDY #.LOW.XTVBLL JSR SETVBV JMP CLMJMP .PAGE NCA .BYTE 'NO CARTRIDGE' SCMG .BYTE CR HILO NCA ; ; ; ******* RUN AT ADDRESS ******* ; ; ; BRUN .WORD BRMG JSR GETLIN JSR GETNO JSR PERX STA RAMLO STX RAMLO+1 LDA CTR CMP #4 BEQ MOUT1 ;RETURN TO MENU IF NO RUN ADDRESS GIVEN JSR INITIO ;CLOSE ALL IOCB'S, THEN REOPEN S/E JMP LMTR ;LOAD MEM.SAV & JUMP TO ADDRESS ; ; BRMG .BYTE 'RUN FROM WHAT ADDRESS?',CR .PAGE ; **** CREATE MEM.SAV FILE ON DISK **** ; ; MEMS .BYTE 'TYPE ',$22,'Y',$22,' TO CREATE MEM.SAV',CR MEMSAV .WORD MEMS JSR CHRGET ;GET CHAR (CR) CMP #'Y BNE  MOUT ;BRANCH IF USER'S ANSWER NOT A Y JSR MEMSVQ ;TRY TO OPEN MEM.SAV BMI MCONT ;IF FILE DOESN'T EXIST THEN JUMP LDA #.LOW.MEMSGL ;ELSE 'MEMORY.SAVE' AREADY EXIST LDX #.LOW.MEMSGH ; JSR DSPLIN ;DISPLAY THIS FACT MOUT JSR CLOSX ;EXIT AFTER CLOSING IOCB1 MOUT1 JMP MENUSL ; ; ; WRITE MEMORY.SAVE TO DISK ; MCONT JSR MWRITE ;WRITE FILE BPL MOUT MERR JMP CIOER1 ;DISPLAY ERROR ; MEMSG .BYTE 'MEM.SAV FILE ALREADY EXISTS',CR HILO MEMSG .PAGE ; **** WRITE DOS & DUP **** ; ; WBOOT .WORD DOSDRV ;ADDRESS OF DRIVE # PROMPT ; ; RETRIEVE DRIVE NUMBER FROM USER. ; JSR GETLIN ;GET INPUT JSR GETDN ;GET DRIVE AS NUMBER, VERIFY IT JSR PERX ;EXIT IF ERROR STA UNNO ;SAVE IT FOR TSTVER2 ORA #'0 ;TURN BACK TO ASCII REP STA DS+1 ;STORE IN DOS.SYS FILE SPEC STA QWMG+31 ;& IN PROMPT ; JSR TSTVER2 ;TST IF VERS. 2 DISK - IF ISNT WONT RTRN ; ; ASK USER IF CAN WRITE DOS & DUP TO SPECIFIED DRIVE ; LDA #.LOW.QWMGL ;PRINT PROMPT LDX #.LOW.QWMGH JSR DSPLIN JSR CHRGET CMP #'Y BNE WBX ;EXIT UNLESS Y ; ;TELL USER WRITING DOS FILES AND WRITE DOS.SYS FIRST- JUST OPEN IT. ; LDA #.LOW.WBMGL LDX #.LOW.WBMGH JSR DSPLIN ; LDA #OPEN LDX #$10 ;OPEN DOS.SYS ON IOCB #1 STA ICCOM,X ;WILL CAUSE FMS TO REWRITE BOOT SECTOR LDA #.LOW.DSL ;& A COPY OF DOS.SYS STA ICBAL,X LDA #.LOW.DSH STA ICBAH,X LDA #8 STA ICAX1,X JSR CIOCL ;DO OPEN, IF ERROR GOTO MENU ; LDX #$10 LDA #CLOSE STA ICCOM,X JSR CIOCL ;DONE CLOSE IT. ; ; WRITE DUP.SYS - SWAP AREA FILE ; LDX #11 ;MOVE 11 CHARS MDUPBL LDA DUPSYS-1,X STA PAR-1,X  ;MOVE FILE NAME TO PARAMETER LIST DEX BNE MDUPBL LDA DS+1 ;GET DRIVE NUMBER STA PAR+1 ;PUT IT IN DUP.SYS FILE SPEC ; STX PTR LDX #$10 JSR PIOCB  ;PUT FILE NAME POINTER IN IOCB LDA #.LOW.DTHL STA LDST LDA #.LOW.DTHH STA LDST+1 LDA #.LOW.NMDUP STA LDND LDA #.LOW.LENL STA WDRL+1 LDA #.LOW.LENH STA WDRH+1 LDA #.HIGH.NMDUP STA LDND+1 PHA ;NO /A LDA #.LOW.DOSOS STA RUNAD LDA #.HIGH.DOSOS STA RUNAD+1 ;SET DUP.SYS RUN ADDRESS DEC RUNQ+1 ;SET RUN FLAG JMP NRUNAD ;WRITE DUP.SYS WBX JMP MENUSL DOSDRV .BYTE 'DRIVE TO WRITE DOS FILES TO?',CR WBMG .BYTE 'WRITING NEW DOS FILES',CR HILO WBMG .PAGE QWMG  .BYTE 'TYPE ',$22,'Y',$22,' TO WRITE DOS TO DRIVE .',CR HILO QWMG DS .BYTE 'D1:DOS.SYS',CR HILO DS WVD .BYTE 'ERROR - NOT VERSION 2 FORMAT.',CR HILO WVD .PAGE ; **** TEST FOR VERSION 2 FORMAT - SUBROUTINE **** ; ; ; ; SUBROUTINE - TSTVER2 ; ; READS THE DISK'S VTOC AND CHECKS IF VERSION BYTE IS SET AS 2. ; ; ENTRY - DRIVE # STORED IN UNNO ; EXIT - RETURNS ONLY IF IS A VERSION 2 DISK ;  ELSE DOES AN ERROR EXIT BACK TO MENU ; CALLS - DRVSTAT AND RVTOC ; CALLED BY - DELFIL, RENFIL, WBOOT. ; ; ; GET DRIVE TYPE SO KNOW CORRECT SECTOR SIZE - NEEDED FOR RVTOC ; TSTVER2 = * LDA #0  ;GET DRIVE TYPE IN SECSIZ STA SECSIZ ;ASSUME 256 - NEEDED BY RVTOC LDA UNNO ;GET DRIVE # JSR DRVSTAT ;FIND OUT TYPE - CARRY FLAG BCS OKTYP ;BRANCH IF 256 TYPE  LDA #$80 ;ELSE SET AS 128 BYTE DEVICE STA SECSIZ ; ; READ THE VTOC & CHECK IF VERSION 2 ; OKTYP JSR RVTOC ;READ IN VTOC TO DBUF LDA DBUF ;1ST BYTE IS VERSION # CMP  #2 ;IS IT VERSION 2? BEQ SMVRS ;YES, SAME VERSION - RETURN ; ; NOT A VERSION 2 DISK - PRINT MSG & GOTO MENU ; LDA #.LOW.WVDL ;ELSE, NOT SAME VERSION LDX #.LOW.WVDH ;PRINT INCOMPATIBLE MSG JSR DSPLIN JMP MENUSL ;GOTO MENU ; ; DISK IS VERSION TWO SO RETURN ; SMVRS RTS ;RETURN .PAGE ; **** LOAD USER FILE FUNCTION **** ; ; LDFIL .WORD LFMG JSR GETIC1 LDA #0 LDX OPT STA OPT CPX #'N ;IS OPTION N FOR DON'T LOAD AND GO? BNE NOTN ;BRANCH IF NOT DEC OPT NOTN JSR PERX JSR LOAD  CPX #0 ;PROCESS LOAD SUBR RESPONSE BEQ LDFX ;BRANCH IF LOAD WAS OK CPX #3 BEQ NLF ;IF BAD LOAD FILE TYA ;OTHERWISE WE GOT A CIO ERROR JMP  CIOER ;GO SAY WHAT IT IS NLF LDA #.LOW.BLFL LDX #.LOW.BLFH JSR DSPLIN ;BAD LOAD FILE MSG JSR CLOSX ;CLOSE THE FILE LDFX JMP MENUSL ;EXIT BLF .BYTE 'BAD LOAD FILE',CR HILO BLF LFMG .BYTE 'LOAD FROM WHAT FILE?',CR .PAGE ; **** LOCK & UNLOCK FILE COMMANDS **** ; ; LKFIL .WORD LKMG ;DO LOCK JSR GETIC1 JSR PERX LDA #LOCK  LDX #$10 STA ICCOM,X JSR CIOCL JMP MENUSL LKMG .BYTE 'WHAT FILE TO LOCK?',CR ; ULFIL .WORD ULMG ;DO UNLOCK JSR GETIC1 JSR PERX LDA #UNLOCK LDX #$10 STA ICCOM,X JSR CIOCL JMP MENUSL ULMG .BYTE 'WHAT FILE TO UNLOCK?',CR .PAGE ; **** DUPLICATE DISK ROUTINE **** ; ; DDMG .BYTE 'DUP DISK-SOURCE,DEST DRIVES?',CR OK .BYTE 'TYPE ',$22,'Y',$22,' IF OK TO USE PROGRAM AREA',CR HILO OK CMSI .BYTE 'CAUTION: A ',$22,'Y',$22,' INVALIDATES MEM.SAV.',CR HILO CMSI ; ; RVTOC READS VOLUME TABLE OF CONTENTS SECTOR ; RVTOC LDA #1 STA DSHI  ;READ VTOC SECTOR LDA #$68 STA DSLO LDA #.LOW.DBUFH STA DBUFHI LDA #.LOW.DBUFL STA DBUFLO ;POINT DCB AT DBUF JSR RSEC1 LDA #0 STA PTR  LDA DBUF+$A STA CSRC ;BYTE OF ALLOC MAP LDA #8 STA IPTR ;COUNT BITS IN BYTE LDA #0 STA DSHI ;POINT TO SECTOR ONE LDA #1 STA DSLO RTS ; ; DUPDSK .WORD DDMG LDA #0 ;ASSUME SINGLE DRIVE STA TWODRV ;CLEAR FLAG JSR GETLIN JSR GETDN STA UNNO ;UNIT NO FOR READ JSR GETDN STA CDES ;CDES IS THE DEST DRIVE # JSR PERX ; ; DETERMINE THE DRIVE TYPES OF THE SOURCE AND DESTINATION DRIVES ; IF THEY ARE NOT THE SAME THEN ERROR - PRINT MSG AND GOTO MENU. ; IF THEY ARE THE SAME THEN SET SECSIZ FOR BUFFER INCREMENT IN ; DUP PORTION. ; LDA #$80 ;ASSUME SOURCE IS 128 BYTE/SECTOR STA SECSIZ ;SECSIZ IN LSB,MSB ORDER LDA #0 STA SECSIZ+1 ; LDA UNNO ;CHECK SOURCE FIRST, DO STATUS TEST JSR DRVSTAT ;SETS CARRY IF 256, 128 THEN CARRY CLR BCC ONE28 ;BRANCH IF 128 DEVICE LDX #0 ;ELSE SET SECSIZ AS 256 BYTES STX SECSIZ INX STX SECSIZ+1 ; ; CHECK STATUS ON DESTINATION AND SEE IF COMPATIBLE ; ONE28 LDA CDES ;DO STATUS ON DEST JSR DRVSTAT BCC IS128 ;128,YES TEST FOR 128 IN SECSIZ BIT SECSIZ ;ELSE CHK FOR 256 IN SECSIZ BPL SAME ;BRANCH IF DES & SRC ARE 256 ; ; NOT THE SAME THEN PRINT MSG AND GOTO MENU. ; INCOMP LDA #.LOW.NCDRL ;PRINT INCOMPATIBLE DRIVE LDX #.LOW.NCDRH  ;MSG JSR DSPLIN JMP MENUSL ;GOTO MENU ; ; 128 BYTE CHECK ; IS128 BIT SECSIZ ;IF LSB NOT 80 HEX THEN 256 SRC BPL INCOMP ;AND THEN INCOMPATIBLE ; ; CHECK IF TWO DRIVE OR SINGLE DRIVE DUP ; SAME LDA UNNO CMP CDES ;IF BOTH UNITS THE SAME BEQ SDD ;SINGLE DRIVE DUP LDX #.LOW.IBDH LDA #.LOW.IBDL JSR DSPLIN ;PROMPT TO INSERT BOTH DISKS JSR CHRGET DEC TWODRV ;SET TWO DRIVE FLAG BMI DODKDP ;GO DUP DISK .PAGE IBD .BYTE 'INSERT BOTH DISKS, TYPE RETURN',CR HILO IBD NCDR .BYTE 'ERROR - DRIVES INCOMPATIBLE.',CR HILO NCDR ; ; ;USED BY BOTH SINGLE & DOUBLE DRIVE DUP. WILL NOT ASK TO SWAP IF 2 DRIVE ;FLAG (TWODRV) IS SET. ;IF THE TWO DRIVE FLAG IS CLEAR WILL ;FILL FROM SOURCE DISK, SWAP, EMPTY, SWAP, REPEAT. ; SDD LDA #.LOW.ISDL ;TELL USER TO INSERT SOURCE LDX #.LOW.ISDH ;FOR INITIAL READ - USED ONLY FOR SINGLE JSR DSPLIN ;DRIVE DUPLICATE JSR CHRGET DODKDP LDA #.LOW.NMDUPL ;SET BUFFER AT END OF DUP STA STVEC  LDA #.LOW.NMDUPH STA STVEC+1 ; ; BUFFER BOTTOM MOVES FROM NMDUP TO MEMTOP ; SET END OF BUFFER TO MEMTOP MINUS 1 SECTOR IN BYTES. ; WHEN BUFFER BOTTOM IS LESS THAN OR EQUAL TO BUFFER END, AT ; LEAST ONE MORE SECTOR WILL FIT IN MEMORY. ; LDA MEMTOP SEC SBC SECSIZ ;T1 IS END OF BUFFER STA T1 LDA MEMTOP+1 SBC SECSIZ+1 STA T1+1 ;T1 IS MEMTOP MINUS SECTOR SIZE. ; ;SEE IF ROOM FOR AT LEAST ONE SECTOR! ; LDA T1 ;DO DOUBLE PRECISION TEST CMP STVEC ;TO SEE IF ROOM LDA T1+1 ;IF T1 IS = STVEC THEN ENUF ROOM SBC STVEC+1 ;FOR ONE SECTOR BCS ENUF ;BRANCH IF (T1)>=(STVEC) NORM LDA #NRML LDX #NRMH JSR DSPLIN JMP MENUSL ; ENUF JSR CKMEM ;SEE IF OK TO USE USER AREA LDA #0 STA OPT ;SET UP FOR READ HERE FIRST PASS JSR RVTOC ;READ VTOC LDA DSLO ;COPY INITIAL WRITE POINTERS STA SWDP ;TO INITIAL READ POINTERS LDA DSHI STA SWDP+1 LDA PTR STA SWDP+2 LDA IPTR STA SWDP+3 LDA CSRC STA SWDP+4 JMP LRS1 ;SKIP FIRST READ PROMPT ; ;READ FROM SOURCE DISK TIL BUF FULL OR END OF DATA. ; DORD LDA #0 ;FLAG WE ARE READING STA OPT BIT TWODRV ;TEST FOR 2 DRIVES BMI LRS1 ;YES, SKIP THE SWAP LDA #.LOW.ISDL ;INSERT SRC DISK LDX #.LOW.ISDH XBLK JS R DSPLIN JSR CHRGET ; ;SWAP POINTERS TO WHERE WE ARE ; LRS1 JSR DOSWDP ;SWAP SECTOR AND BITMAP POINTERS ; ;LOOP READING/WRITING SECTORS TO BUFFER AREA ; LRS JSR AAM ;ADVANCE ALLOCATION MAP BMI  ASPT ;IF FREE, ADV SECTR POINTER & TRY AGIN BIT OPT ;SEE WHAT MODE BMI DOW ;BR IF WRITE JSR RSEC1 ;DO READ JMP IOD DOW JSR DKWRT ;DO WRITE IOD LDA DBUFLO ;ADVANCE BUFFER POINTER CLC ADC SECSIZ ;ADD SECTOR SIZE TO BOTTOM OF BUFFER STA DBUFLO ;SO POINT TO NEXT FREE BLOCK LDA DBUFHI ADC SECSIZ+1  STA DBUFHI ASPT JSR ASP ;GO ADVANCE SECTOR POINTER BEQ STDD1 ;ALL SECTORS DONE, SWAP TO DEST DISK LDA T1 ;SEE IF ROOM FOR ANOTHER CMP DBUFLO ;SECTOR BELOW MEMTO P LDA T1+1 SBC DBUFHI BCS LRS ;BRANCH IF (DBUF)<=(T1) - ROOM FOR MORE. ; ;SWAP DISKS AND CONTINUE ; STDD LDA OPT BMI DORD ;IF WAS WRITE, GO READ STDD2 DEC OPT  ;CHANGE TO WRITE BIT TWODRV ;ARE 2 DRIVES BEING USED? BMI LRS1 ;YES, SKIP THE SWAP LDA #.LOW.IDDL ;INSERT DEST DISK LDX #.LOW.IDDH JMP XBLK ;GO DO WRITE STDD1 LDA OPT ;END OF DATA BPL STDD2 ;IF READ GO WRITE JMP MENUSL ;IF WRITE WE ARE DONE ; ;DOSWDP - EXCHANGE CURRENT AND SAVED BITMAP & SECTOR POINTERS ;ALSO INIT BUFFER POINTER ; DOSWDP LDY  #4 SWLOP LDA SWATL,Y STA RAMLO LDA SWATH,Y STA RAMLO+1 ;GET ADDRESS FROM TABLE TO RAMLO LDX #0 LDA (RAMLO,X) ;GET WHAT'S THERE PHA LDA SWDP,Y STA (RAMLO,X) PLA STA SWDP,Y DEY BPL SWLOP LDA STVEC STA DBUFLO LDA STVEC+1 STA DBUFHI RTS ; ; WHAT A MESS ; HILO DSLO HILO DSHI HILO PTR HILO IPTR HILO CSRC .PAGE SWATL .BYTE DSLOL,DSHIL,PTRL,IPTRL,CSRCL SWATH .BYTE DSLOH,DSHIH,PTRH,IPTRH,CSRCH ; ; NRM .BYTE 'NOT ENOUGH ROOM',CR ISD .BYTE 'INSERT SOURCE DISK,TYPE RETURN',CR IDD .BYTE 'INSERT DESTINATION DISK,TYPE RETURN',CR HILO NRM HILO ISD HILO IDD ; ; ; AAM - ADVANCE ALLOCATION MAP ONE BIT. ; RETURN MINUS IF FREE. ; AAM ASL CSRC ;NEXT BIT OF ALLOC MAP  DEC IPTR BNE CBIT ;IF DONE WITH THIS BYTE INC PTR ;GET NEXT ONE LDX PTR LDA DBUF+$A,X ;VTOC IS DBUF & BITMAP STRTS IN 10TH BYT STA CSRC LDA #8 STA IPTR CBIT LDA CSRC ;CHECK THE BIT RTS ; ; ; ASP - ADVANCE SECTOR POINTER IN DCB. ; RETURN EQ IF AT END. ASP LDA DSLO ;SEE IF END CMP #208 BNE NXS LDA DSHI CMP #2 BEQ ASPX ;ALL DONE NXS INC DSLO BNE ASPX INC DSHI ASPX RTS ; ; RSEC1 - READ A SECTOR WHOSE NUMBER IS IN DCB ; RSEC1 LDA UNNO STA DUNIT CLC  ;TELL DISK HANDLER DOING A GET SECTOR PHP ;SAVE FLAG JMP CLDKH ; ; DKWRT - WRITE A SECTOR ; DKWRT LDA CDES ;PUT DEST UNIT # STA DUNIT ;IN DCB SEC  ;TELL DISK HANDLER DOING WRITE SECTOR PHP ;SAVE FLAG CLDKH LDA #2 ;SET RETRY COUNT STA RCNT CLD1 LDX #1 ;SET DRIVE TYPE- ASSUME 128 BIT SECSIZ ;TEST FOR 128 BMI NOT256 ;IF IS BRANCH INX ;ELSE SET FOR 256 NOT256 PLP PHP ;SET ACTION FLAG & SAVE IT FOR RETRY JSR BSIOR ;GOTO FMS DISK HANDLER  BPL DRTS ;RETURN IF GOOD STATUS ; DEC RCNT ;ELSE SEE IF MORE RETRIES BPL CLD1 ;YES, DO AGAIN JMP CIOER1 ;CIO ERROR, GO SAY WHICH DRTS PLP ;EVEN OUT STACK RTS ;RETURN ; ; CKMEM - ASK IF OK TO USE USER AREA ; CKMEM LDA WARMST ;IF MEMORY WAS INTACT BEQ CPTR1 ;QUERY TO BOMB IT LDA #.LOW.OKL LDX #.LOW.OKH  ;PRINT PROMPT JSR DSPLIN LDA #.LOW.CMSIL ;PRINT CAUTION MSG LDX #.LOW.CMSIH ;Y RESPONSE WILL INVALIDATE MEM.SAV JSR DSPLIN JSR CHRGET CMP #'Y ;TEST FOR OK TO BOMB USER AREA BNE DDXT ;IF SAY NO THEN DON'T DO DUP LDA #0 STA WARMST ;TELL CART NO GOOD USER MEMORY STA MEMFLG ;TELL LOADER NO GOOD MEM.SAV CPTR1 RTS ; DDXT PLA  ;POP RETURN ADDRESS PLA JMP MENUSL ;GOTO MENU, DON'T DO DUP ; ; ; DRVSTAT - SUBROUTINE TO DO STATUS ON DISK DRIVE SPECIFIED ; BY THE NUMBER IN REG. A. ; RETURNS - CARRY SET = DEVICE HAS 256 BYTE SECTORS ; CARRY CLR = DEVICE HAS 128 BYTE SECTORS ; DRVSTAT STA DUNIT ;STORE UNIT NUMBER IN DCB LDA #STAREQ ;STORE STATUS COMMAND IN DCB STA DCOMND LDA #2  ;SET RETRY COUNT STA RCNT DOSTAT JSR DKHND ;DO STATUS WITH OS HANDLER BPL CHKTYP ;IF GOOD RETURN, DETERMINE TYPE ; DEC RCNT ;ELSE SEE IF ANOTHER RETRY BPL DOSTAT ! ;YES, DO AGAIN JMP CIOER1 ;ELSE ERROR EXIT ; CHKTYP CLC ;ASSUME 128 BYTE DEVICE LDA DVSTAT ;GET COMMAND STATUS BYTE AND #$20 ;MASK FOR DRIVE TYPE BIT- D5 BEQ " RETSTAT ;128 IF = 0 SEC ;256 IF = 1 RETSTAT RTS ; **** DUPLICATE FILE COMMAND **** ; ; ; DUPLICATE FILE FROM ONE DISK TO ANOTHER ;USING ONE DRIVE. FILENAME FOR DUPLICATE FILE IS SAME AS ;SOURCE NAME. US#ER CAN ENTER ONLY THE SOURCE FILE SPECIFICATION. ;USER HAS OPTION OF USING PROGRAM AREA FOR COPY OR A 250 BYTE ;DATA BUFFER TO GET PROGRAM AREA USER MUST RESPOND WITH ;'Y' AS 1ST CHAR OR THEY WILL GET THE DATA BUFFER. WILL DUPLICATE ;FILE OF ANY SIZE. I$F ERROR, PRINTS MSG, CLOSES FILE(S) OPEN AND ;RETURNS TO MENU. TO PREVENT POSSIBLE DAMAGE TO DESTINATION ;DISK, FILE IS OPENED AND CLOSED FOR EACH WRITE. ;MAKES BUFR LEN AN EVEN MULTIPLE OF 125. THIS PREVENTS FRAGMENTATION ;OF THE FILE DUE TO THE APPE%ND OPEN FUNC. 125 IS USED BECAUSE IT IS THE ;SIZE OF DATA PORTION IN A SECTOR. IF THIS CHANGES THE VALUE IN THE PGM ;MUST BE CHANGED. ; K.B. 5/7/80 ; DPFM .BYTE 'NAME OF FILE TO MOVE?',CR ; DUPFIL .WORD DPFM ;DUPLICATE FILE PROM&PT JSR GETIC1 ;GET FILENAME TO DUPLICATE ON SAME DRIVE JSR PERX ;DON'T COME BACK IF PARAMETER ERRORS LDA PAR CMP #'D ;DUPLICATE FILE ONLY FOR DISK DEVICE BEQ ISD'ISK JMP ODMS ;IF NOT -- SAY CANNOT DO & EXIT ; ISDISK JSR USEPGM ;ASK USER IF TO USE PROG AREA OR BUFFER ; ; HAVE USER INSERT SOURCE FILE AND HIT WHEN DONE ; LDX #.LOW.ISDH ;ARG: LINE TO (BE DISPLAYED ADDR LDA #.LOW.ISDL ;IN REG. A & X JSR DSPLIN ;PRINT INSERT SOURCE MSG JSR GETLIN ;GOTO SCREEN & WAIT FOR JSR PERX ;GOTO MENU IF BREAK KEY HIT ; )JSR LOOKWC ;SEE IF FILE SPEC. USES WILDCARDS BNE NOWC ;BRANCH IF NO WILD CARDS USED - USE OLD ROUTINE LDA #$40 ;SET 'DUPLICATE WILDCARD' MODE JMP WCINIT ;OPEN WILDCARD DIREC*TORY FILE, ETC. ; NOWC = * ; ; MAKE SURE DEST NOT DOS.SYS ; LDX #0 ;ENTRY-INDEX TO FIRST CHAR OF FILE NAME JSR TSTDOS ;WON'T RETURN IF IS DOS.SYS ; ; OPEN SOURCE FILE - ADDR OF FILENAME+ STRING IN PARAM LIST IS ; ALREADY ASSIGNED TO IOCB # 2 ; WCDUPS LDX #$10 ;USE IOCB #2 LDA #OPEN ;OPEN COMMAND STA ICCOM,X LDA #4 ;READ ONLY STA ICAX1,X , JSR CIOCL ;CALL CIO - IF ERR PRNT MSG,CLOSE, GOTO MENU ; ; EOFFLG - SOURCE FILE EOF FLAG FTRF - FLAG TO SHOW IF 1ST TIME SOURCE ; FILE WAS READ ; LDA #0 STA EOFFLG ;CLEAR EOF FLAG STA FTRF - ;CLEAR MEANS FIRST TIME ; ; DO UNTIL (SOURCE EOF FLAG (EOFFLG) IS SET) ; SET UP IOCB#2 TO DO GET CHAR. ZP LOC BUFADR HAS BUFFER ADDRESS ; BUFLEN HAS BUFFER LENGTH ; DODUP LDX #$10 ;USE IOCB #2 LDA BUFADR . ;IN LSB,MSB ORDER STA ICBAL,X ;SET BUFFER ADDR IN IOCB #2 LDA BUFADR+1 STA ICBAH,X LDA BUFLEN ;IN LSB,MSB ORDER STA ICBLL,X ;STORE BUFFER LENGTH LDA B/UFLEN+1 ;IN IOCB #2 STA ICBLH,X LDA #GETCHR ;COMMAND TO GET CHAR - IGNORE EOL'S (9B) STA ICCOM,X JSR CIO ;CALL CIO ; ; CHECK FOR ENDFILE. IF YES, THEN SET FLG. CHECK FOR ER0R. IF ERR ; THEN PRINT MSG, CLOSE FILE, AND RETURN TO MENU. ; BPL INSDES ;IF GOOD READ WRITE BUFFER CPY #EOF ;WAS IT EOF? BEQ SETFLG ;YES, THEN SET FLAG JMP CIOER1 1 ;WAS ERR - PRINT MSG,CLOSE,GOTO MENU SETFLG DEC EOFFLG ;SET ENDFILE FLAG ; ; WHEN GOOD READ OR EOF GET HERE. ASK USER TO INSERT DESTINATION ; DISK AND ATTEMPT TO WRITE TO DESTINATION FILE. ; INSDES LDX #.LOW.IDDH 2 ;ARG: ADDRESS OF LINE TO BE PRINTED LDA #.LOW.IDDL ;IN REGS A AND X JSR DSPLIN ;SAY TO SWAP DISKS JSR GETLIN ;WAIT TIL USER HITS BIT PER ;WAS BREAK KEY HIT? 3 BPL DODEST ;NO, TRY WRITE JMP CLSSRC ;YES, CLOSE & GOTO MENU ; ; CHECK IF FIRST TIME SRC WAS READ. IF YES, THEN OPEN FOR OUTPUT ; ONLY. OTHERWISE, OPEN FOR OUTPUT APPEND. ; DODEST LDX #$20 4 ;USE IOCB #3 FOR DESTINATION LDY #9 ;ASSUME APPEND LDA FTRF ;IS FLAG CLEAR? BNE OPNDES ;NO,NOT FIRST TIME - OPEN APPEND LDY #8 ;YES, THEN OPEN OUT ONLY 5 INC FTRF ;SET TO SHOW NOT FIRST TIME NEXT TIME ; OPNDES TYA ;GET OPEN TYPE CODE STA ICAX1,X ;SET AUX1 BYTE LDA #OPEN ;OPEN COMMAND STA ICCOM,X ; ; THE FI6LENAME IS THE FIRST FILE IN THE PARAMETER LIST-PAR. ; LDA #PARL ;SET BUFR ADDR TO FILE SPEC TO BE OPENED LDY #PARH BIT WCFLAG ;IF WLDCARD-WLDCARD BUFR INSTEAD OF PAR BVC SKIPWC ; 7 LDA #.LOW.WCBUF2 LDY #.HIGH.WCBUF2 ; SKIPWC STA ICBAL,X TYA STA ICBAH,X JSR CIOCL ;CALL CIO, IF ERROR GOTO MENU ; ; CHECK IF SOURCE BUFR LEN IS NOT EQUAL TO ZERO. IF NOT = ZERO ; 8 THEN WRITE BUFFER TO THE DESTINATION FILE. ; LDY #$10 ;SOURCE IS AT IOCB #2 LDX #$20 ;DEST IS AT IOCB #3 LDA #0 ;CHECK LENGTH LOW FOR ZERO CMP ICBLL,Y ;LOW=0 9 BNE DOWRIT ;NO THEN WRITE BUFFER CMP ICBLH,Y ;IS HI=0? BEQ CLSDES ;YES, DON'T WRITE EMPTY BUFFER ; DOWRIT LDA #PUTCHR ;PUT CHAR COMMAND CODE STA ICCOM,X ;IGNOR:E EOLS (9B) LDA BUFADR ;GET BUFFER ADDRESS STA ICBAL,X LDA BUFADR+1 STA ICBAH,X LDA ICBLL,Y ;GET BUFFER LENGTH TO WRITE STA ICBLL,X ;FROM IOCB OF SOURCE FIL;E LDA ICBLH,Y ;SET BY GET TO ACTUAL BYTE STA ICBLH,X ;COUNT READ INTO BUFFER JSR CIOCL ;DO WRITE - IF ERR GOTO MENU ; ; CLOSE DESTINATION FILE ; CLSDES LDA #CLOSE ;CLOSE  LDA #.LOW.ISDL ;REGS A AND X JSR DSPLIN ;SAY TO INSERT SOURCE JSR GETLIN ;WAIT TIL USER HITS BIT PER ;WAS BREAK KEY HIT? BMI CLSSRC ;YES, CLOSE & GOTO? MENU JMP DODUP ;REPEAT LOOP ; ; ******************END OF LOOP******************* ; ; CLOSE SOURCE AND RETURN TO MENU ; CLSSRC LDX #$10 ;SOURCE AT IOCB #2 LDA #CLOSE ;CLOSE COMMAND @CODE STA ICCOM,X JSR CIO ;CALL CIO ; BIT WCFLAG ;TEST IF 'DUPLICATE WILDCARD' MODE BVC DUPFEX ;BR IF NOT 'DUPLICATE WILDCARD' MODE LDX #.LOW.ISDH ;INSERT SOURACE MESSAGE LDA #.LOW.ISDL JSR DSPLIN ;NEEDED TO GET NEXT WILDCARD DIR ENTRY JSR GETLIN ;WAIT FOR CR JSR PERX ;IF BREAK-KEY ABORT - EXIT TO MENU JMP WCOPYL B;JUMP TO WILDCARD LOOP DUPFEX = * ; JMP MENUSL ;GO TO THE MENU .PAGE ; **** ASK IF OK TO USE PROGRAM AREA ROUTINE **** ; ; ;ASK USER IF CAN USE PROGRAM AREA. IF SAY YES ('Y') THEN ;ASSIGN BUFFER ADDRESS AS ACLL AVAILABLE MEMORY. OTHERWISE, USE ;DBUF (250 BYTES) AS THE BUFFER. ASSIGNS BUFFER LENGTH. ; ;NO PARAMETERS ;RETURNS: BUFADR-BUFFER ADDRESS ; : BUFLEN-BUFFER LENGTH ; USEPGM LDA WARMST ;CHECK IF PGM AREA ALREADY BEQ USEDDB4 ;USED-YES, USE IT AGAIN LDA #.LOW.OKL ;ARGS: IN A AND X ADDR LDX #.LOW.OKH ;OF LINE TO DISPLAY JSR DSPLIN ;ASK TO USE PGM AREA LDA #.LOW.CMSIL ;SAY A Y RESPONSE WILL E LDX #.LOW.CMSIH ;INVALIDATE MEM.SAV JSR DSPLIN ;PRINT CAUTION JSR CHRGET ;GET 1ST CHAR OF CMP #'Y ;USERS RESPONSE BNE USEBUF ;NO, THEN USE DBUFF ; ;USEF ALL MEMORY AVAILABLE-PROGRAM AREA ;MEMLO,MEMTOP,BUFADR,BUFLEN ARE IN LSB,MSB FORM ; USEDB4 LDA #0 ;CLEAR WARMSTART FLAG STA WARMST ;TO SHOW PGM AREA USED STA MEMFLG ;SHOW NO USER AREA GOOD-MEMG.SAV ALSO LDA #.LOW.NMDUPL ;USE ALL AVAILABLE STA BUFADR ;MEMORY-FROM END OF DUP TO MEMTOP LDA #.LOW.NMDUPH ;BUFADR HAS BUFFER STA BUFADR+1 ;ADDRESS LDA MEMTOP ;GHET LENGTH OF SEC ;PGM AREA SBC #.LOW.NMDUPL STA BUFLEN ;LSB,MSB ORDER LDA MEMTOP+1 SBC #.LOW.NMDUPH STA BUFLEN+1 ; ; FIND THE GREATEST MULTIPLE OF 12I5 LESS THAN THE PROGRAM AREA ; THEN SET BUFR LEN TO IT. THIS PREVENTS FRAGMENTATION TO FILE ; WHEN APPEND IS USED IN DUPFIL. ; LDA #0 ;INIT MULTIPLE OF 125 (MLT125) TO ZERO STA MLT125 STA MJLT125+1 ; ; DO UNTIL (MLT125 > BUFLEN) ; FINDGM LDA #125 ;INC THE MULTIPLE OF 125 BY 125 CLC ;TO GET THE NEXT HIGHER MULTIPLE ADC MLT125 STA MLT125 LDA #0 ADC K MLT125+1 ;MLT125 IS IN LSB,MSB ORDER STA MLT125+1 ; ; TEST FOR MLT125 > BUFLEN - LOOP TEST ; LDA BUFLEN+1 ;IS MSB OF MLT125 > MSB OF BUFLEN? CMP MLT125+1 BCC GETMLT ;YES, LTHEN END LOOP BNE FINDGM ;IF MLT LSB BUFLEN? BCS FINDGM ;NO, REPEAT LOOP ;M ;ELSE END LOOP. ;********************** END OF LOOP*********************** ; ; CHECK IF MULTIPLE = TO 125. IF IS, THEN LEAVE BUFLEN AS IS. IF ; ISN'T THEN SET BUFLEN TO THAT NULTIPLE OF 125 MINUS 125. ; GETMNLT LDA MLT125+1 ;IS MSB NOT = ZERO? BNE REPLAC ;YES, VALUE IS > 125 LDA #125 ;IS LSB > 125? CMP MLT125 BCC REPLAC ;YES, REPLACE BUFLEN WITH MLT125 RTS O ;ELSE LEAVE BUFLEN AS IS ; REPLAC LDA MLT125 ;SUBTRACT 125 FROM MLT125 TO GET SEC ;GREATEST MULTIPLE LESS THAN OR EQUAL SBC #125 ;TO THE PROGRAM AREA. STA BUFLENP ;USE IT AS THE BUFFER LENGTH. LDA MLT125+1 SBC #0 STA BUFLEN+1 RTS ;RETURN ; ;USE BUFFER DBUF (250 BYTES) INSTEAD OF PROGRAM AREA ; USEBUF LDA #.LOW.DBUFL ;USE DBUF AS Q STA BUFADR ;BUFFER ADDRESS LDA #.LOW.DBUFH ;IN LSB,MSB ORDER STA BUFADR+1 LDA #EDBLL ;STORE DATA STA BUFLEN ;BUFFER LENGTH LDA #EDBLH ;=TO 256(R100HEX) STA BUFLEN+1 ;IN LSB,MSB ORDER RTS ;RETURN .PAGE ; **** CHECK FILENAME FOR WILDCARD CHARACTERS **** ; ; ; CHECKS THE STRING AT PAR,X FOR WLDCARD CHARACTERS (* OR ?). IF ; STHEY ARE FOUND THE ROUTINE SETS THE = FLAG. IF A IS FOUND ; RETURNS TO THE CALLING ROUTINE WITH THE EQUAL FLAG RESET. ; LOOKWC LDA PAR,X INX CMP #'* BEQ LOOKW2 CMP #'? BEQ LOOKW2 T CMP #CR BEQ LOOKW1 CMP #', ;TERMINATE WITH CR OR COMMA BNE LOOKWC ; LOOKW1 INX LOOKW2 RTS .PAGE ; **** TEST FILE SPEC FOR DOS.SYS **** ; ; ; SUBROUTINE - TSTDOS ; ; CHECKS UA FILE SPEC IN THE STORAGE LOC FOR DOS.SYS. USED TO ; PREVENT COPYING TO A FILE NAMED DOS.SYS. IF DOS.SYS IS OPENED ; OUTPUT FMS WILL WRITE A COPY OF DOS OUT TO THE FILE. ; ; ENTRY - REG X HAS INDEX INTO PAR TO FIRST CHAR OF FILE SPEVC ; ASSUMES COMPLETE FILE SPEC. ; EXIT - WILL NOT RETURN IF FILE NAME = DOS.SYS, BUT GOES TO MENU. ; ; FIND END OF DEVICE ID - COLON ; TSTDOS INX ;NEVER IS FIRST CHAR LDA PAR,X ;GET 2WND CHAR CMP #': ;IS IT A COLON? BEQ GOTCOL ;YES, THEN NAME STARTS AT CHAR 3 INX ;ELSE NAME STARTS AT CHAR 4 GOTCOL INX ;POINT AT FIRST CHAR OF NAME ; ; CXOMPARE FILE NAME IN PAR WITH DOS.SYS ; LDY #0 ;INDEX INTO DOS.SYS FILE SPEC ; NXTCHAR LDA DS+3,Y ;GET NEXT DOS.SYS CHAR CMP PAR,X ;TEST IF FILE NAME IS SAME BNE NOTSAM ;NO,Y THEN RETURN INY INX ;ELSE TRY NEXT CHAR CPY #7 ;ARE THERE MORE CHARS TO TRY? BNE NXTCHAR ;YES, DO AGAIN ; ; FILE NAME EQUALS DOS.SYS - ERROR EXIT ; LDA #Z.LOW.DCDSL ;PRINT MSG - DEST CAN'T BE DOS.SYS LDX #.LOW.DCDSH JSR DSPLIN JMP MENUSL ;GOTO MENU ; ; NOT EQUAL TO DOS.SYS - RETURN TO CALLER ; NOTSAM RTS ; DCDS .BYTE 'DESTINATION CANT BE DOS.SY[S',CR HILO DCDS .PAGE ; **** SAVE FILE ROUTINE **** ; ; SAVFIL .WORD SFMG LDA #0 STA INITQ+1 STA RUNQ+1 JSR GETIC1 LDA OPT PHA LDX PTR \ ;PUT EOL ON FILENAME LDA #CR STA PAR-1,X JSR GETNO ;GET HEX PARAMETER STA LDST STX LDST+1 CPX #.LOW.NDSH BCS DSLMFG ;BRANCH IF NOT SAVING DUP AREA ] DEC WDR1+1 DSLMFG JSR GETNO ;END ADDRESS STA LDND STX LDND+1 SEC SBC LDST STA WDRL+1 TXA SBC LDST+1 BPL ADDOK ;BR IF ENDING ADDR >^ THAN STARTING JMP MENUSL ;ELSE BACK TO MENU ADDOK STA WDRH+1 CPY #CR BEQ NRUNAD ;BRANCH IF NO MORE PARAMS JSR GETNO ;GET A RUN ADDRESS IF ANY STA INITAD _ STX INITAD+1 ORA INITAD+1 BEQ NINTAD ;BRANCH IF NO INIT ADDRESS GIVEN DEC INITQ+1 ;SET FLAG NINTAD CPY #CR BEQ NRUNAD ;BRANCH IF NO RUN ADDRESS GIVEN JSR G`ETNO ;GET RUN ADDRESS JSR PERX ;CHECK FOR ERRORS STA RUNAD STX RUNAD+1 ORA RUNAD+1 BEQ NRUNAD ;BRANCH IF NO RUN ADDRESS DEC RUNQ+1 ;SET FLAG NaRUNAD LDA #0 STA OPT PLA ;OPTION CHAR FROM FILENAME CMP #'A ;IF APPEND BNE *+5 DEC OPT ;SET OT=$FF ; ; OPEN THE FILE ; LDX #$10 bLDA #OPEN STA ICCOM,X BIT OPT ;IF APPEND BMI *+6 LDA #8 BNE *+4 LDA #9 STA ICAX1,X JSR CIOCL ; ; WRITE SAVE FILE HEADER ; LDA #PUcTCHR STA ICCOM,X LDA #.LOW.SAVHL STA ICBAL,X LDA #.LOW.SAVHH STA ICBAH,X LDA #6 STA ICBLL,X LDA #0 STA ICBLH,X BIT OPT BPL d WHEAD ;BRANCH IF NOT APPEND LDA #4 STA ICBLL,X LDA #.LOW.LDSTL STA ICBAL,X LDA #.LOW.LDSTH STA ICBAH,X WHEAD JSR CIOCL ; ; WRITE DATA RECORD ; WDR LDX #$10e WDRL LDA #0 ;THIS IMMEDIATE VALUE MODIFIED STA ICBLL,X WDRH LDA #0 ;THIS IMMEDIATE VALUE MODIFIED STA ICBLH,X INC ICBLL,X BNE *+5 INC ICBLH,X LDfA LDST STA ICBAL,X LDA LDST+1 STA ICBAH,X WEX JMP WDR1 SFMG .BYTE 'SAVE-GIVE FILE,START,END(,INIT,RUN)',CR .PAGE ; **** MISC. SUBROUTINES **** ; ; GETLIN LDA #CR LDX #79 g STA LINE,X DEX BPL *-4 LDA #0 STA PTR STA IPTR STA PER JSR CIOGET JSR SCROL RTS ; ; ; ; CIOGET - GET LINE OF INPUT FROM SCREEN EDITOR ; CIOGETh LDA #GETREC STA ICCOM ;SCREEN EDIT IOCB LDA #LBUFL STA ICBAL LDA #LBUFH STA ICBAH LDA #80 STA ICBLL LDA #0 STA ICBLH LDX i #0 JSR CIO ;READ RECORD FROM SCREEN EDITOR CPY #$80 ;CHECK FOR BREAK ABORT STATUS BNE *+5 DEC PER ;PARAM ERROR FLAG IS SET IF SO RTS ; ; ; CHRGET - GET 1 CHARj FROM EDITOR IN A. ; CHRGET LDA #0 STA PER CHRG1 JSR CIOGET ;GET A LINE FROM E: LDA ICBLL ;SAVE CHAR COUNT STA RCNT JSR SCROL LDA PER BPL CHRG2 k ;IF BREAK, CLOSE AND EXIT JSR CLOSX JMP MENUSL CHRG2 LDA RCNT ;EXPECT 1 OR 2 CHARACTERS CMP #3 BMI CHRG3 ;IF OK LDA #.LOW.OLL LDX #.LOW.OLH JSRl DSPLIN JMP CHRG1 ;TRY AGAIN CHRG3 LDA LINE ;GET 1ST CHAR RTS .PAGE OL .BYTE 'PLEASE TYPE 1 LETTER',CR HILO OL ; ; PERX - EXIT IF PARAMETER ERRORS ; PERX BIT PER m BMI PERX1 RTS PERX1 PLA PLA JMP MENUSL ; ; GETIC1 - READ LINE, GET FILENAME, POINT TO IT IN IOCB1 ; GETIC1 JSR GETLINE GETIC2 LDX #$10 JSR PIOCB JMP GETFIL ; ; GETNAME LDA #8 n ;ENTRY TO GETFIL USED BY RENAME STA CTR ;WHICH DOES NOT HAVE A DEVICE ID LDY PTR ;FOR THE SECOND FILE SPEC LDX IPTR JMP CFTE ; ; SUBROUTINE - GETFIL ; REMOVES ONoE FILE SPECIFICATION FROM THE INPUT LINE. WILL SET UP ; THE SPEC FOR DEFAULTS FOR INCOMPLETE DRIVE ID. DEFAULT DRIVE # ; IS 1. ; ; ;GET FILESPEC FROM INPUT LINE GETFIL LDY PTR LDX IPTR LDA #11 STA CTpR ; ;AVOID GETTING JUNK ON VERY SHORT PARAMS ; LDA LINE,X CMP #', BEQ ADDC CMP #CR BEQ ADDC LDA LINE+1,X CMP #', BEQ GT1 CMP #CR BEQ qGT1 LDA #': ;LOOK FOR : IN FILESPEC CMP LINE+2,X ;SEE IF HAVE COMPLETE FILESPEC ALREADY BEQ CFTE CMP LINE+1,X BNE GT1 DEC CTR LDA LINE,X CMP r #'A BPL CFTE ;HAVE X:FILE, COMPLETE FILESPEC ; ;IF FALLS THRU, IS UNIT:FILE, ADD D ; GT2 LDA #'D STA PAR,Y INY BPL CFTE GT1 DEC CTR DEC CTR CMP LINE,X s ;AN UNLIKELY CASE (:FILE) BEQ GT2 ;TREAT FILE AS U:FILE DEC CTR ADDC LDA #'D STA PAR,Y INY LDA #': STA PAR,Y INY CFTE LDA #0 STA OPT CtFTE1 LDA LINE,X STA PAR,Y INX INY CMP #CR ;LOOK FOR TERMINATOR BEQ EOC CMP #', BEQ EOC CMP #'/ BEQ POPT CMP #'. u ;LOOK FOR START OF .EXT BNE CFTE2 LDA #4 ;FOUND, 4 MORE CHARS MAX STA CTR CFTE2 DEC CTR BPL CFTE1 ; ;GETS HERE IF TOO MANY CHARS IN FILENAME ; LDA #.LOW.NTLL LDX v #.LOW.NTLH JSR DSPLIN ;NAME TOO LONG DEC PER ;SET PARAMETER ERROR FLAG STE LDA LINE,X ;SKIP TO END INX CMP #', BEQ EOC CMP #CR BNE STEw EOC STX IPTR STY PTR RTS POPT LDA LINE,X STA OPT INX LDA LINE,X STA PAR-1,Y ;CHANGE STORED TERMINATOR TO , OR CR I HOPE INX BPL EOC NTL .BYTEx 'NAME TOO LONG',CR HILO NTL ; ; DSPMSG - DISPLAY N BYTES ; BUFFER POINTER AND LENGTH ARE ALREADY IN IOCB0 ; DSPMSG LDA #PUTCHR STA ICCOM LDX #0 ; CIO1 JSR CIO ;CALL CIO AND GO TO MENUSL y CPY #$80 ;IF BREAK KEY ABORT BNE *+5 JMP MENUSL RTS ; ; DSPLIN - DISPLAY ONE LINE OF TEXT ; A=LO,X=HI ADDRESS DSPLIN JSR PRNTMSG ;USE RESIDENT DUP SUBROUTINE JMP SCROL z ;SCROLL SCREEN BELOW MENU & RETURN ; ; ; SCROL - DO SCROLLING OF AREA BELOW MENU ; SCROL LDA #0 TAX STA ICBLH,X LDA #10 STA ICBLL,X LDA #.LOW.ZAPH STA ICBAH,X LDA { #.LOW.ZAPL STA ICBAL,X JMP DSPMSG .PAGE ZAP .BYTE CUP,CUP,CUP,CUP,CUP .BYTE DLL,CDN,CDN,CDN,CDN HILO ZAP ; ; PIOCB - POINT IOCB AT PAR(PTR) ; PIOCB LDA #PARL CLC ADC |PTR STA ICBAL,X LDA #PARH ADC #0 STA ICBAH,X RTS ; ; CIOCL - CALL CIO AND PROCESS ANY ERRORS ; CIOCL JSR CIO ;CALL CIO TYA BMI *+3 RTS } ;OK, RETURN CIOER1 TYA ;ERROR STATUS CIOER SEC SBC #100 ;ERROR NUMS ALWAYS ARE 1XX DEC LDX #'0-1 ;CONVERT TENS CTNS INX SEC SBC #10 BPL CTNS ~ ;THE EASY (SLOW) WAY CLC ADC #10+'0 ;CONVERT STA EUN STX ETN LDX #.LOW.CIEH LDA #.LOW.CIEL CIEX JSR DSPLIN JSR CLOSX ;CLOSE IOCBS 10,20  JMP MENUSL CIE .BYTE 'ERROR- 1' ETN .BYTE 0 EUN .BYTE 0 .BYTE CR HILO CIE ; ; ; GETNO - GET HEX NUMERIC PARAMETER FROM LINE(IPTR). ; RETURN A=LO, X=HI. PER SET MINUS IF ERROR. ; INC IPTR PAST PARAM. ; GETNO LDA #4 ;MAX NO DIGITS STA CTR LDA #0 STA T1 STA T1+1 ;INIT TEMP TO BUILD NUMBER IN GHB LDX IPTR LDA LINE,X ;GET CHAR INC IPTR CMP #CR ;SEE IF TERMINATOR BEQ GND CMP #', BEQ GND JSR HEXCON ;CONVERT ASCII TO NIBBLE BMI ERRX ;IF ERROR LDY #3 ;SHIFT T1,T1+1 BY 4 SHT1 CLC ROL T1+1 ROL T1 DEY BPL SHT1 ORA T1+1 ;OR IN NEW NIBBLE STA T1+1 DEC CTR ;COUNT DIGIT BPL GHB ;LOOP UNLESS TOO MANY DIGITS LDA #.LOW.TMDL LDX #.LOW.TMDH ERRX1 JSR DSPLIN DEC PER RTS GND TAY LDA T1+1 LDX T1 RTS ERRX LDA #.LOW.IHPL ;INVALID HEX PARAM  LDX #.LOW.IHPH BNE ERRX1 TMD .BYTE 'TOO MANY DIGITS',CR HILO TMD IHP .BYTE 'INVALID HEXADECIMAL PARAMETER',CR HILO IHP ; ; ; HEXCON - CONVERT ASCII CHAR IN A TO HEX NIBBLE IN A. RETURN ; MINUS CONDITION, A=FF IF ERROR. ; HEXCON SEC SBC #'0 BMI ERRX2 ;ASCII BELOW '0' CMP #10 BMI OKX ;0-9 CONVERTED SO EXIT SEC SBC #'A-'0-10 CMP #10  ;CONVERTED VALUE MUST BE 10 OR MORE BMI ERRX2 ;BETWEEN '9' AND 'A' CMP #$10 BMI OKX ;A-F CONVERTED ERRX2 LDA #$FF OKX CMP #0 ;SET STATUS BY VALUE IN A RTS ; ; GETDN - GET A DEVICE NUMBER FROM LINE(IPTR) ; RETURN IT IN A ; GETDN BIT PER ;SEE IF PARAM ERROR ALREADY BMI GDR ;IF SO DON'T BOTHER LDX IPTR GETD LDA LINE,X INX  CMP #'D ;IF DN BEQ GETD ;GO GET DIGIT SEC SBC #'0 ;CONVERT DIGIT BEQ BDS ;CAN'T BE ZERO BMI BDS ;IF NOT DIGIT CMP #5  BPL BDS ;TOO LARGE PHA GD1 LDA LINE,X INX CMP #', BEQ GDX ;IF TERMINATOR CMP #CR BNE GD1 ;KEEP LOOKING GDX STX IPTR  ;ADVANCE POINTER PLA GDR RTS BDS DEC PER LDA #.LOW.NDSL ;NEED DEVICE SPEC MSG LDX #.LOW.NDSH JMP DSPLIN NDS .BYTE 'NEED D1 THRU D4',CR NMDUP .BYTE 0 LEN = NMDUP-EDN  HILO LEN MLEN = NMDUP-NDOS HILO MLEN HILO NDS HILO NMDUP .END u LIST X .TITLE 'DUP FOR DUAL DENSITY VER 2D.1 11/18/80'^ H ; ; ;CHANGED FOR SYSTEM RESET -- DUPFLG ;ADDED INTERRUPT ROUTINES FROM SIO -- KB ;ADDED SAVE/RESTORE OF DOSINI VECTOR -- KB ; ; FILENAME = DK1:DP256Q.SRC^ H ; .PAGE ; **** EQUATES ****^ H ; ; ; CIO = $E456 DKHND = $E453 SETVBV = $E45C SYSVBV = $E45F XITVBV = $E462 CIOINV = $E46E MEMTOP = $2E5 IRQEN = $D20E BRKKEY = $11 POKMSK = $10 DOSVEC =  $A DOSINI = $C ;DOS INIT VECTOR WARMST = 8 LMARGN = $52 RMARGN = $53 CARTST = $BFFA INTRVEC = $20A ;INTERRUPT VECTOR LOC FOR SIO PATCH MEMLO = $2E7 SHFLOK = $2BE INITAD = $2E2 RUNAD = $2E0 ICHIDZ = $20 ICDNOZ = $21 ICBALZ = $24 ICBAHZ = $25 ICIDNO = $2E MAXDEV = $21 HATABS = $31A USRDOS = $1700 FMS = $700 FMINIT = FMS+$E0 DOS = FMS+$E40 WRMSTR = $E474 ;WARM START ENTRY VECTOR BSIOR = $772 ;ENTRY POINT TO FMS DISK HANDLER USED BY DUP DISK CDTMV3 = $21C ;ADDRESS OF SYSTEM TIMER # 3 CDTMF3 = $22A ;ADDRESS OF TIMER # 3 DONE FLAG ; CR = $9B CUP = $1C CDN = $1D CLF = $1E CRT = $1F DLL = $9C CLSCR = $7D EOF = $88 ;ENDFILE RETURN CODE FROM CIO ; ; OPEN = $03 CLOSE = $0C PUTCHR =  $0B GETCHR = $07 GETREC = $05 PUTREC = $09 RENAME = $20 DELETE = $21 FORMAT = $FE LOCK = $23 UNLOCK = $24 STAREQ = $53 ;STATUS COMMAND TO DISK CONTROLER ; IOCB1 = $10 ; DVSTAT = $2EA ;ADDRESS OF STATUS INFO STORED BY OS ; ; DCB = $300 DUNIT = DCB+1 DCOMND = DCB+2 DSTATS = DCB+3 DBUFLO = DCB+4 DBUFHI = DCB+5 DSLO = DCB+$A DSHI = DCB+$B ; IOCB = $340 ICHID = IOCB+0 ICDNO = IOCB+1 ICCOM = IOCB+2 ICSTA = IOCB+3 ICBAL = IOCB+4 ICBAH = IOCB+5 ICBLL = IOCB+8 ICBLH = IOCB+9 ICAX1 = IOCB+10 ICAX2 = IOCB+11 ; SYSED  = $0 OWRIT = $08 ORDWRT = $0C ; HILO .MACRO P1 P1&H = .HIGH.P1 P1&L = .LOW.P1 .ENDM .PAGE ; **** ZERO PAGE VARIABLES ****^ H ; ; *=$18 JMPTBL *=*+2 RAMLO *=*+2 BUFADR = RAMLO ;SAVE AREA FOR BUFFER ADDRESS USED BY USEPGM .PAGE ; **** INIT CODE FOR DUP ****^ H ; ; ; INITIALIZATION CODE FOR DUP - CALLS FMS INIT CODE. ; CALLED ON WARM START AND COLD START. ; *=DOS LDA #0  STA OPT LDA #MNDUPL STA DOSVEC LDA #MNDUPH STA DOSVEC+1 LDA #.LOW.ISRSIR ;SET UP INTERRUPT VECTORS FOR SIO PATCH. STA INTRVEC ;INSTEAD OF USING THE SERIAL INPUT READY  LDA #.HIGH.ISRSIR ;SERVICE ROUTINE AND THE SERIAL OUTPUT STA INTRVEC+1 ;INTERRUPT SERVICE ROUTINE IN THE OS ROM LDA #.LOW.ISRODN ;USE THE VERSIONS IN RAM FOLLOWING THE STA INTRVEC+2 ;RESIDENT PORTION OF DUP. LDA #.HIGH.ISRODN STA INTRVEC+3 JSR FMINIT LDA WARMST ;ON COLDSTART, LOAD AUTORUN.SYS BNE CKMDOS ;WARMSTART CHECK IF DUP WAS RUNNING LDA #AFL STA ICBAL+$10 LDA #AFH STA ICBAH+$10 JSR INITX ;CLEAR DUPFLG SHOW DUP NOT IN MEMORY. LDA #$C0 JSR STLOAD ;LOAD, INIT AND RUN THE AUTORUN FILE JMP CLOSX ;MAKE SURE IOCB #1 IS CLOSED & RETURN ; CKMDOS LDA DUPFLG ;SEE IF DUP WAS IN MEMORY BEQ INITX ;=ZERO THEN WASN'T ; LDA MEMFLG ;SEE IF USER AREA WRITTEN TO MEM.SAV BEQ CLDSET ;=ZERO THEN WASN'T JSR LDMEM1  ;ELSE GET USER MEMORY BACK IN ; JSR RELDIN ;RESTORE THE DOSINI VECTOR FROM SAVE LOC JSR INITX ;CLEAR DUPFLG JMP WRMSTR ;REDO WARMSTART ; INITX LDA #0 ;SAY DUP NOT IN MEMORY STA DUPFLG ;CLEAR FLAG RTS ; CLDSET STA WARMST ;NO VALID USER MEMORY BEQ INITX ;SET TO COLD START .PAGE ; **** LOADER ROUTINE ****^ H ; ; ; LOADS FROM THE FILE (MUST BE LOAD FORMAT) ; INTO MEMORY. RETURNS: ; X=0 LOAD OK ; X=1 OPEN ERRORS Y=CIO CODE ; X=2 READ ERRORS Y=CIO CODE ; X=3 BAD LOAD FILE ; ON ENTRY, IOCB 1 POINTS TO FILENAME. ; DUPFLG .BYTE 0 ;FLAG -IF DUP IN MEMORY NOT ZERO OPT .BYTE 0  ;HOLDS VALUE OF OPTION GIVEN BY USER LOADFG .BYTE 0 ;FLAG = $80 IF MEMORY FILE DOESN'T HAVE TO BE LOADED HDBUF *=*+4 HILO HDBUF SFLOAD LDA #$80 STLOAD STA LOADFG LOAD LDA #.LOW.RTS STA RUNAD  LDA #.HIGH.RTS STA RUNAD+1 ;MAKE RUN AT EOF DEFAULT TO RTS LDX #$10 LDA #OPEN STA ICCOM,X LDA #4 ;OPEN TYPE=INPUT STA ICAX1,X JSR CIO ;TRY TO OPEN FILE BPL RDLF ;CONT IF OK LDA #1 ;OPEN ERRORS BNE CLFX ;CLOSE AND EXIT RDLF LDX #$10 LDA #DBUFL STA ICBAL,X LDA #DBUFH STA ICBAH,X  LDA #2 STA ICBLL,X LDA #0 STA ICBLH,X STA MEMLDD ;CLEAR MEM.SAV LOADED FLAG LDA #GETCHR STA ICCOM,X JSR CIO BMI ERST ;IF ERRS LDA  #$FF CMP DBUF ;CHECK FOR VALID LOAD FILE BNE LNLF CMP DBUF+1 BNE LNLF ;BRANCH IF NOT A LOAD FILE RDDRC LDX #$10 LDA #HDBUFL STA ICBAL,X LDA #HDBUFH  STA ICBAH,X LDA #4 RDDRC1 STA ICBLL,X LDA #0 STA ICBLH,X JSR CIO ;NO ERROR CHECK SO CAN CATCH EOF BPL STOK ;IF NO ERROR CPY #$88 ;SEE IF EOF  BNE ERST ;IF SOME ERROR STATUS ; ;EOF SO DONE, EXIT ; JSR CLOSX ;CLOSE IOCB'S 1 AND 2 BIT OPT BMI DRUN ;BRANCH IF NO RUN OPTION JSR JMPRUN ;JUMP THROUGH RUN VECTOR DRUN LDA  #0 ;OK STATUS BIT LOADFG ;WAS MEMORY SWAPPED? STA LOADFG BMI CLFX ;BRANCH IF MEMORY WASN'T SWAPPED JSR MEMSVQ ;DOES MEMORY SAVE FILE EXIST? BMI DRUN1 ;BRANCH IF NOT PLA PLA JMP GOOD ;WRITE MEMORY AND RELOAD DUP ; ; SEE IF DUP WRITTEN OVER. IF IS RELOAD & TELL USER NEED MEM.SAV TO ; LOAD THIS FILE. ; DRUN1 LDA DUPFLG ;SEE IF DUP CLOBBERED BNE DRUN2 ;NO, THEN RETURN LDA #NMSFL ;ELSE TELL USER NEED MEM.SAV LDX #NMSFH JSR PRNTMSG ;PRINT MSG JMP RRDUP ;RELOAD & RUN DUP ; ; RETURN TO CALLING ROUTINE ; DRUN2 LDA #0 ;NO DUP ERR MSG ON EOF CLFX TAX RTS RTS ; ; ERROR RETURNS ; LNLF JSR CLOSX LDA #3 ;BAD LOAD FILE BNE CLFX ERST TYA PHA JSR CLOSX PLA TAY BNE CLFX ; ; CONTINUE WITH LOAD - CHECK LOAD ADDRESS FOR HEADER ; HEADER IF HAVE CONCATENATED LOAD FILES ; STOK LDX #$10 LDA HDBUF ;MOVE PARAMS TO IOCB STA ICBAL,X PHA LDA HDBUF+1 STA ICBAH,X TAY  PLA INY ;WAS ADDRESS FF? BNE ADOK ;BRANCH IF NOT TAY INY ;OTHER BYTE FF? BNE ADOK ;BRANCH IF NOT ; ; HAVE A HEADER & START ADDRESS - GET END ADDRESS FOR TEXT & DO AGAIN ; LDA HDBUF+2 STA HDBUF LDA HDBUF+3 STA HDBUF+1 ;MOVE LOAD ADDRESS LDA #.LOW.HDBUF+2 STA ICBAL,X LDA #.HIGH.(HDBUF+2) STA ICBAH,X ;SO LOAD ADDRESS DOESN'T GET WIPED OUT BY END ADDRESS LDA #2 JMP RDDRC1 ; ; GET LENGTH OF TEXT. THEN DETERMINE IF IN DUP ; ADOK LDA HDBUF+2 SEC SBC HDBUF STA ICBLL,X LDA HDBUF+3 SBC  HDBUF+1 STA ICBLH,X LDA HDBUF+1 JSR AWDQ ;IS BEGINNING ADDRESS WITHIN DUP? BCS AWD ;BRANCH IF SO LDA HDBUF+3 JSR AWDQ ;IS ENDING ADDRESS WITHIN DUP? BCS AWD ;BRANCH IF SO ; ; SINCE TEXT IN DUP, LOAD MEM.SAV IF NECCESARY ; ANWD LDA MEMLDD BMI AWD ;BRANCH IF MEM.SAV ALREADY LOADED LDA #$80 ORA LOADFG STA LOADFG ;SET MEM.SAV DOESN'T HAVE TO BE LOADED FLAG AWD INC ICBLL,X BNE *+5 INC ICBLH,X BIT LOADFG ;DOES MEMORY HAVE TO BE LOADED BMI DLM ;BRANCH IF NOT LDA MEMLDD ;WAS MEM.SAV ALREADY LOADED?  BMI DLM ;BRANCH IF SO DEC MEMLDD JSR LDMEM ;LOAD MEM.SAVE FILE (IF IT EXISTS) LDA #0 ;SHOW USER AREA NOT DUP IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOSINI VECTOR ; ; SET NO INIT ADDR DEFAULT THEN READ IN TEXT & ATTEMPT INIT ; DLM LDX #$10 LDA #.LOW.RTS STA INITAD LDA #.HIGH.RTS STA INITAD+1 ;INIT DEFAULTS TO AN RTS JSR CIO ;READ DATA DIRECTLY TO MEMORY BPL DLM1 JMP ERST ;IF ERRORS DLM1 BIT OPT BMI DINIT ;BRANCH IF NOGO OPTION JSR JMPINT ;DO INIT DINIT JMP RDDRC ;GET NEXT SECTION OF LOAD FILE ; ;  SUBROUTINE TO DETERMINE IF ADDRESS IS WITHIN DUP ADDRESS SPACE. ; ENTRY - HI BYTE OF ADDRESS IN REG. A ; RETURNS - CARRY SET : WITHIN DUP ; CARRY CLR : NOT WITHIN DUP ; AWDQ CMP #NDOSH  BCC AWDQR ;BRANCH IF HI BYTE LT DUP START CMP #NMDUPH+1 ROL A EOR #1 LSR A ;COMPLEMENT CARRY AWDQR RTS ; ; JMPINT JMP (INITAD) JMPRUN JMP (RUNAD) ; ; MEMLDD .BYTE 0 AF  .BYTE 'D1:AUTORUN.SYS',CR HILO AF NMSF .BYTE 'NEED MEM.SAV TO LOAD THIS FILE.',CR HILO NMSF .PAGE ; **** CREATE MEM.SAV FILE ****^ H ; ; ;ROUTINE WRITTEN BY MICHAEL EKBERG,APRIL 21,1980 ;THIS ROUTINE CREATES A FILE ON DISK OF DATA FROM MEMORY ;CREATE FILE CALLED 'D1:MEM.SAV',SET Y=1 ; ;THE RAM TO BE OCCUPIED BY DUP IS STORED BY THIS ROUTINE INTO 'MEMORY.SAV' ; ; NAME .BYTE 'D1:MEM.SAV',CR HILO NAME MWRITE JSR CLOSX ;CLOSE IOCB AND OPEN IT TO WRITE LDA #OWRIT ; STA ICAX1,X ; JSR OREST ;OPEN FOR WRITE BMI ERRWR ;IF ERROR THEN JMP AND RET ; ; ;WRITE MEMORY BLOCK ; LDA #PUTCHR STA ICCOM,X LDA #NDOSL ;STORE START OF BLOCK FOR CIO STA ICBAL,X LDA #NDOSH ;START ADDR (HIGH) STA ICBAH,X LDA #MLENL+1 ;LENGTH OF BLOCK STA ICBLL,X LDA #MLENH ;LENGTH(HIGH)  STA ICBLH,X JSR CIO ;WRITE DATA BLOCK BMI ERRWR ;IF WRITE ERROR THEN JMP JSR CLOSX BMI ERRWR LDY #0 RET RTS ; OREST LDA #OPEN STA ICCOM,X LDA #NAMEL ;ROUTINE TO COMPLETE OPEN OF 'D1:MEMORY.SAV STA ICBAL,X ;CALLING SUB SUPPLIES 'READ' OR 'WRITE' LDA #NAMEH ;IN ICAX1 STA ICBAH,X JMP CIO ; ERRWR STY TEMP+1 ;TEMP STORE FOR Y FLAG JSR CLOSX ;CLOSE #$20 LDA #DELETE ;DELETE PART OF MENSAV STA ICCOM,X JSR OREST TEMP LDY #0 ;RESTORE FLAG RTS RETURN TO MAIN CALLER .PAGE ; **** ENTRY POINT ON 'DOS' CALL ****^ H ; ; INISAV .DBYTE 0 ;DOSINI VECTOR SAVE AREA MEMFLG .BYTE 0 MNDUP LDX #0 STX MEMFLG STX LOADFG DEX STX WARMST JSR INITIO JSR MEMSVQ ;FIND OUT IF FILE D1:MEM.SAV EXISTS BPL GOOD ;BRANCH IF MEM.SAV FILE EXITS LDA #0 STA WARMST ;CLEAR WARM START FLAG BEQ FINAL ; ; GOOD JSR MWRITE ;WRITE USER AREA TO MEM.SAV BMI ERROR DEC MEMFLG ;SHOW MEMORY WRITTEN BMI FINAL ; ERROR LDA #.LOW.ERRMES ;PRINT ERROR OCCURED MSG LDX #.HIGH.ERRMES JSR PRNTMSG ;GOTO MSG PRINTER ; LDA #.LOW.ERR ;PRINT QUERY TO RUN DOS LDX #.HIGH.ERR JSR PRNTMSG ;GOTO MSG PRINTER ; ; WAIT FOR Y TO RUN DOS ; LDA #GETREC STA ICCOM LDA #STAKL STA ICBAL LDA #STAKH  STA ICBAH LDA #2 STA ICBLL LDA #0 STA ICBLH JSR CIO LDA STAK ;SEE IF Y TYPED CMP #'Y BNE RTCART ;BRANCH IF NOT LDA #0 STA WARMST ; FINAL LDX #$20 LDA #CLOSE STA ICCOM,X ;SET UP CLOSE COMMAND JSR CIO ;PERFORM CLOSE COMMAND ; RRDUP LDA DOSINI ;SAVE DOSINI VECTOR STA INISAV LDA DOSINI+1 STA INISAV+1 ; LDA #.LOW.DOS ;SET UP DUP INIT ADDRESS AS DOSINI VECTOR STA DOSINI LDA #.HIGH.DOS STA DOSINI+1 ; RRDUP1 LDA #.LOW.DUPSYS LDX #$10 STA ICBAL,X  LDA #.HIGH.DUPSYS STA ICBAH,X LDY #0 STY OPT ;ASSURE NO /N OPTION IN EFFECT DEY ;SHOW THAT DUP IS IN MEMORY STY DUPFLG JSR SFLOAD ;LOAD DUP.SYS AND RUN IT RTCART RTS EC .BYTE 'E:',CR HILO EC HILO MNDUP DUPSYS .BYTE 'D1:DUP.SYS',CR ; ERRMES .BYTE 'ERROR-SAVING USER MEMORY ON DISK',CR ERR .BYTE 'TYPE Y TO STILL RUN DOS',CR .PAGE ; **** SUBROUTINES FOR RESIDENT DUP ****^ H ; ; ; ROUTINE TESTS IF MEM.SAV IS PRESENT ON THE DISK. ; RETURNS - MINUS IF NOT THERE ; PLUS IF MEM.SAV IS THERE ; MEMSVQ JSR CLOS20 ;CLOSE IOCB # 2 LDA #OPEN STA ICCOM,X LDA #NAMEL STA ICBAL,X LDA #NAMEH STA ICBAH,X LDA #ORDWRT STA ICAX1,X ;TRY TO OPEN D1:MEM.SAV FOR READ/WRITE JSR CIO PHP ;SAVE STATUS  JSR CLOS20 ;CLOSE MEM.SAV PLP ;RESTORE STATUS RTS ; ; ; SAVE FILE SUBROUTINE - WRITE FILE BODY, INIT, & RUN VECTORS ; WDR1 LDA #0 ;THIS IMMEDIATE VALUE MODIFIED BEQ WDR2 ;BRANCH IF MEMORY FILE DOESN'T HAVE TO BE LOADED JSR LDMEM WDR2 LDX #$10 JSR CIO ;DO SAVE - WRITE BODY TO DISK INITQ LDA #0 ;THIS IMMEDIATE VALUE CHANGED DURING SAVE BEQ RUNQ ;SET TO FF WHEN AN INIT VECTOR IS PRESENT INC INITQ+1 LDA INITAD STA VECTR ;IF INIT VECTOR FOR FILE SAVE IT LDA INITAD+1 STA VECTR+1 LDA #.LOW.INITAD TAX STA LDST  LDA #.HIGH.INITAD JSR WRVEC RUNQ LDA #0 ;THIS IMMEDIATE VALUE MODIFIED BEQ NORNAD ;SET TO FF WHEN A RUN VECTOR IS PRESENT INC RUNQ+1 LDA RUNAD STA VECTR ;IF RUN VECTOR FOR FILE SAVE IT LDA RUNAD+1 STA VECTR+1 LDA #.LOW.RUNAD TAX STA LDST LDA #.HIGH.RUNAD JSR WRVEC NORNAD JSR CLOSX ;CLOSE IOCBS 1 &2 LDA MEMFLG AND WDR1+1 BEQ DRRDUP INC WDR1+1 ;RESET MEM.NEEDS TO BE LOADED FLAG JMP RRDUP1 ;RELOAD & RUN DUP DRRDUP JMP DOSOS ;RUN THE SWAPPED IN DUP ; ; ; WRVEC STA LDST+1 INX  STX LDND STA LDND+1 LDX #$10 LDA #.LOW.LDST STA ICBAL,X LDA #.HIGH.LDST STA ICBAH,X LDA #6 STA ICBLL,X LDA #0 STA ICBLH,X  JMP CIO ;WRITE INIT OR RUN ADDRESS ; ; ; JUMP TO CARTRIDGE ; CLMJMP JSR LDMEM LDA #0 ;SHOW DUP NO LONGER IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOSINI VECTOR JMP (CARTST)  ;JUMP TO CARTRIDGE ; ; ; LOAD MEM.SAV (IF IT EXISTS) BEFORE RUN AT ADDRESS ; LMTR JSR LDMEM ;LOAD MEM.SAVE IF IT EXISTS LDA #0 ;SHOW THAT DUP NO LONGER IN MEMORY STA DUPFLG JSR RELDIN ;RESTORE DOSINI VECTOR JMP (RAMLO) ;RUN AT ADDRESS ; ; RESTORE DOSINI VECTOR FROM SAVE AREA ; RELDIN LDA INISAV STA DOSINI LDA INISAV+1 STA DOSINI+1 RTS ; ; ; SUBROUTINE - LDMEM ; LOAD MEM.SAV IF IT EXISTS ; LDMEM LDA MEMFLG BNE LDMEM1 ;BRANCH IF MEMORY WAS SAVED RTS LDMEM1 JSR MEMSVQ BPL LDMEM2 ;BRANCH IF MEM.SAV FILE DOES EXIST LDA #0 ;TELL CART PGM AREA CLOBBERED STA WARMST BEQ CLOS2 ;GO CLOSE AND GOTO CART ; LDMEM2 LDA #OPEN STA ICCOM,X JSR CIO ;REOPEN MEM.SAV LDA #GETCHR STA ICCOM,X LDA #MLENL+1 STA  ICBLL,X LDA #MLENH STA ICBLH,X LDA #NDOSL STA ICBAL,X LDA #NDOSH STA ICBAH,X JSR CIO CLOS2 LDA #CLOSE STA ICCOM,X JMP CIO ;CLOSE MEM.SAV ; ; CLOSE ALL IOCBS & RE-OPEN ZERO AS SCREEN EDITOR ; INITIO JSR CIOINV ;THIS ROUTINE CLOSES ALL IOCB'S ; THEN REOPENS THE SCREEN EDITOR LDX #0 LDA #OPEN STA ICCOM,X LDA #ECL STA  ICBAL,X LDA #ECH STA ICBAH,X LDA #ORDWRT STA ICAX1,X JSR CIO ; LDX #0 ;SET TIMER TO DELAY UNTIL STX CDTMV3 ;SCREEN COMES BACK ON - DMA RESTORED STX CDTMV3+1 ;1ST CLEAR TIMER LDY #1 ;WAIT FOR ONE VBLANK LDA #3 ;USE TIMER #3 STA CDTMF3 ;SET TIME OUT FLAG NON-ZERO JSR SETVBV ;SET VBLANK TIMERS WAITIM LDA CDTMF3 ;WHEN FLAG BECOMES ZERO THEN TIME OUT BNE WAITIM ; RTS ; ; CLOSX - CLOSE IOCBS 10,20 ; CLOSX LDA #CLOSE LDX #$10 STA ICCOM,X JSR CIO ; ; ENTRY TO CLOSE IOCB # 2 ONLY ; CLOS20 LDX #$20  LDA #CLOSE STA ICCOM,X JMP CIO ; ; SUBROUTINE - PRNTMSG ; PUTS A CHARACTER STRING TERMINATED BY A CARRIAGE RETURN CHAR TO ; SCREEN EDITOR. ; ; ENTRY - REG A : LOW BYTE MSG ADDRESS ;  REG X : HI BYTE MSG ADDRESS ; ; PUT PARAMS IN IOCB - USE IOCB 0 FOR SCREEN EDITOR ; PRNTMSG STA ICBAL ;SET MSG ADDR IN IOCB BUFF ADDR STX ICBAH ; ; SET UP REST OF IOCB ; LDA #$80 ;SET IN BUFFER LENGTH STA ICBLL ;ASSUME 128 BYTES MAX LDX #0 ;USE REG X TO SET IN IOCB INDEX FOR CIO STX ICBLH LDA #PUTREC ;PUT MSG STA ICCOM ; ; TEST IF DUP IS RESIDENT - IF IS THEN USE INDIRECT CIO ROUTINE TO TEST ; FOR BREAK KEY ABORT ; LDA DUPFLG ;=ZERO IF NON-RESIDENT DUP NOT IN MEMORY BNE INMEM ;IN MEMORY THEN USE INDIRECT CIO CALL ; JMP CIO ;ELSE GO DIRECT TO CIO & RETURN ; INMEM JMP CIO1  ;USE CIO CALL WITH TEST FOR BREAK KEY ABORT ; ; SAVH .BYTE $FF,$FF HILO SAVH LDST *=*+2 HILO LDST LDND *=*+2 VECTR *=*+2 BUFL = VECTR ;USED BY DUP DISK-STORES SECT SIZE FOR CURRENT MOVE .PAGE ;  **** SIO INTERRUPT SERVICE ROUTINES ****^ H ; ; ; EQUATES FOR INTERRUPT ROUTINES MOVED FROM SIO ; ; ZERO PAGE ; BUFRLO = $32 ;POINTER TO BYTE TO SEND OR RECEIVE BUFRHI = $33 BFENLO = $34 ;POINTER TO BYTE AFTER END OF BUFFER BFENHI = $35 CHKSUM = $31 ;LOC TO STORE DATA FRAME CHECKSUM CHKSNT = $3B ;CHECKSUM SENT FLAG- =FF SENT NOCKSM = $3C ;FLAG NO CHECK SUM TO BE RECEIVED-NOT ZERO STATUS = $30  ;HOLD FOR STATUS TO BE PUT IN DCB BUFRFL = $38 ;FLAG-IF FF RECEIVE BUFFER IS FULL RECVDN = $39 ;FLAG RECEIVE NOT DONE. USED BY WAIT LOOP ; ; HARDWARE REGISTERS USED IN SIO INTERRUPT ROUTINES ; SKRES = $D20A ;SERIAL PORT STATUS RESET ON POKEY SEROUT = $D20D ;SERIAL OUTPUT REGISTER SERIN = SEROUT ;SERIAL PORT INPUT REG ON POKEY SKSTAT = $D20F ;SERIAL PORT STATUS REG ON POKEY ; ; ERROR CODES RETURNED BY SIO ; FRMERR  = $8C ;FRAMING ERROR ON INPUT OVRRUN = $8E ;DATA FRAME OVER RUN-BIT D5 IN SKSTAT CHKERR = $8F ;DATA FRAME CHECKSUM ERROR .PAGE ; **** INTERRUPT SERVICE ROUTINE TO OUTPUT DATA NEEDED ****^ H ; ; ; ; IT UPDATES THE BYTE TO PUT ON SERIAL I/O BUS POINTER ; UNTIL END OF BUFFER. AFTER EACH UPDATE OF THE PTR ADDS THE ; VALUE OF THE BYTE TO THE CHECKSUM. OUTPUTS THE CHECKSUM WHEN ; PTR EQUALS THE END OF BUFFER PTR (POINTS TO BYTE AFTER BUFFER). ; RETURNS TO THIS ROUTINE AFTER CHECKSUM PASSED AND RESETS POKEY ; INTERRUPT REG TO HAVE THE TRANSMIT DONE ROUTINE CALLED TO END ; WAIT LOOP (SEE SIO LISTING). ; ; KEITH BALL 6/10/80 ; ISRODN TYA  ;SAVE Y REG ON STACK PHA ; INC BUFRLO BNE NOWRP0 ;INCREMENT PTR TO NEXT BYTE INC BUFRHI ;TO SEND ; ; PATCH TO ROUTINE CHANGED CHECK ; NOWRP0 LDA BUFRLO ;CHECK IF PTR IS WITHIN BUFFER CMP BFENLO ;DO A DOUBLE PRECISION SUBTRACT LDA BUFRHI SBC BFENHI BCC NOTEND ;BRANCH IF (BUFR) < (BFEN)-MORE TO SEND ; LDA CHKSNT ;TEST IF CHECKSUM ALREADY SENT BNE RELONE ;BRANCH IF ALREADY SENT ; ; SEND CHECKSUM AND SET FLAG ; LDA CHKSUM STA SEROUT ;PUT CHECKSUM IN SERIAL OUT REG DEC CHKSNT ;SET FLAG TO FF HEX BNE CHKDON ;RETURN ; ; AFTER CHECKSUM SENT AND CAUSE NEXT INTERRUPT THEN CHANGE POKEY ; MASK TO ENABLE TRANSMIT DONE INTERRUPT AND TERMINATE WAIT LOOP. ; RELONE LDA POKMSK ;GET POKEY MASK ORA #$08 ;OR IN ENABLE STA POKMSK STA IRQEN ;ENABLE THE INTERRUPTS ; ; RESTORE REGS AND RETURN ; CHKDON PLA TAY ;RESTOR Y REG PLA ;RESTORE A REG SAVED IN OS IRQ INT HNDLR RTI ; ; MORE TO SEND. SEND NEXT BYTE POINTED AT BY BUFR. ; NOTEND LDY #0 LDA (BUFRLO),Y ;GET NEXT BYTE STA SEROUT ;PUT IN SERIAL OUT REG ; CLC ADC CHKSUM ;ADD BYTE TO CHECKSUM ADC #0 STA CHKSUM ; JMP CHKDON ;GO RETURN AND WAIT FOR NEXT BYTE ; ; END OF OUT SERVICE ROUTINE *********************** .PAGE ; **** SERIAL INPUT READY INTERRUPT SERVICE ROUTINE ****^ H ; ; ; ; AFTER SERIAL RECEIVE IS ENABLED ROUTINE IS USED TO COLLECT ; BYTES FROM THE SERIAL INPUT REG AND PUT THEM IN BUFFER. ; WILL STOP WHEN BUFFER IS FULL. IF A CHECKSUM IS EXPECTED ; ROUTINE WILL MARK BUFFER FULL AND CONTINUE. WHEN CHECKSUM ; RECEIVED IT WILL CHECK IF = TO CHECKSUM IT WAS MAKING. ; WILL STORE ERRORS FOUND IN STATUS LOCATION. ; ; THE IRQ INTERRUPT HANDLER IN THE OS PUSHES THE USER'S A REGISTER ; ONTO THE STACK BEFORE CALLING THIS ROUTINE. ; ; KEITH BALL 6/11/80 ; ISRSIR TYA ;SAVE Y REG ON STACK PHA ; ; GET STATUS FROM POKEY THEN RESET IT. ; LDA SKSTAT STA SKRES ;IGNORES VALUE- JUST STROBED ; ; CHECK FOR ERRORS ; BMI NTFRAM ;BIT 8 SET IF NO FRAMING ERROR LDY #FRMERR ; STY STATUS ;SET FRAME ERROR STATUS ; NTFRAM AND #$20 ;IF BIT 5 CLEAR THEN FRAME OVER RUN BNE NTOVRN ;BRANCH IF NO OVER RUN LDY #OVRRUN ; STY STATUS ;ELSE SET OVERRUN ERROR STATUS ; ; CHECK IF BUFFER FULL AND THIS IS A CHECKSUM. IF IT IS, THEN CHECK ; IF DATA SENT WAS VALID. ; NTOVRN LDA BUFRFL ;TEST FOR BUFFER FULL (NOT ZERO) BEQ NOTYET ;IF ZERO THEN NOT YET, THIS IS DATA. LDA SERIN ;ELSE THIS IS CHECKSUM  CMP CHKSUM ;ARE THEY EQUAL? BEQ SRETRN ;YES,THEN RETURN LDY #CHKERR ;ELSE SET CHECK SUM ERROR STATUS STY STATUS ; ; SET RECEIVE DONE TO END WAIT LOOP ; SRETRN LDA #$FF ;DONE VALUE  STA RECVDN ; ; RESTORE REGS AND RETURN ; SUSUAL PLA TAY ;RESTORE Y REG PLA ;RESTORE A REG RTI ; ; IF BYTE IS DATA, THEN GET HERE. PUT BYTE IN BUFFER AND CHECK IF ; AT END OF BUFFER. ; NOTYET LDA SERIN ;GET DATA BYTE LDY #0 ; STA (BUFRLO),Y ;STORE IT IN THE BUFFER ; CLC ; ADC CHKSUM ;ADD DATA BYTE TO CHECKSUM ADC #0 ; STA CHKSUM ; ; INC BUFRLO ;INCREMENT POINTER TO LOCATION BNE NTWRP1 ;FOR NEXT BYTE INPUT INC BUFRHI ; ; THE PATCH CHANGED THE TEST FOR END OF BUFFER ; NTWRP1 LDA BUFRLO ;DO DOUBLE PRECISION SUBTRACT  CMP BFENLO ; LDA BUFRHI ; SBC BFENHI ;CARRY CLEAR IF BORROW BCC SUSUAL ;BR IF (BUFR) < (BFEN)-WITHIN BUFR LIMIT ; ; DONE WITH DATA. SEE IF CHECKSUM TO BE SENT ; LDA NOCKSM ;IF = ZERO THEN A CHECKSUM BEQ GOON ;WILL FOLLOW THE DATA ; LDA #0 ;ELSE NO CHECKSUM TO FOLLOW STA NOCKSM ;CLEAR NO CHECKSUM FLAG BEQ SRETRN ;RETURN AFTER SET RECEIVE DONE FLAG ; ; SET BUFFER FULL AND THEN GO GET CHECKSUM ; GOON DEC BUFRFL ;SET BUFFER FULL FLAG TO FF BNE SUSUAL ;GO RETURN ; ; END OF RECEIVE SERIAL INPUT INTERRUPT ROUTINE********************** MDEND = * HILO MDEND *=$70C .BYTE MDENDL,MDENDH ;SET END ADDR IN FMS PAST RESIDENT DUP SO ; BUFFERS DON'T CLOBBER IT. STAK = $100 HILO STAK .PAGE ; **** BEGINNING OF NON-RESIDENT PORTION OF DUP ****^ H ; ; NDOS = MDEND+$A00 ;END OF SYS BUFRS AND MINIDUP ; ; ROOM FOR 8 256 BYTE DRIVE BUFFERS & 2 256 BYTE FILE BUFFERS ; DRTST = 9 ;ONE BEYOND MAX DRIVES FOR TEST IN GETDN ; HILO NDOS *=NDOS PAR *=*+40 ;PARAMETER AREA PARH  = PAR/256 PARL = (-256)*PARH+PAR LINE *=*+80 ;TYPEIN LINE BUFFER LBUFH = LINE/256 LBUFL = (-256)*LBUFH+LINE DBUF *=*+$100 ;DATA BUFFER FOR COPY DB1 = DBUF+$80 DB3 = DBUF-3 HILO DBUF HILO DB1 HILO DB3 DBLL = 0 DBLH = 1 ;DATA BUFFER LENGTH=$100 EDBLL = $FA ;DATA BUFFER LENGTH USED IN USEPGM EDBLH = 0 ;MUST BE A MULT OF 125, SECT DATA LENGTH MENUSZ *=*+1 PER *=*+1 UNNO *=*+1 RCNT *=*+1 SSTAT *=*+1 SWDP *=*+5 CSRC *=*+1 CDES *=*+1 SAVX *=*+1 PTR *=*+1 IPTR *=*+1 CTR *=*+1 T1 *=*+2 BUFLEN = T1 ;SAVE AREA FOR BUFR LEN, USED IN USEPGM STVEC *=*+2 ;A TEMP OF SOME KIND MLT125 = STVEC ;TEMP STORE FOR MULTIPLE OF 125, USEPGM SECSIZ *=*+2 ;USED TO STORE SECTOR SIZE IN BYTES FOR DUP DISK EOFFLG *=*+1 ;ENDFILE FLAG FOR SOURCE IN DUPFIL FTRF *=*+1 ;FIRST TIME READ FLAG USED IN DUPFIL TWODRV = FTRF ;FLAG TO SHOW IF 1 OR 2 DRIVES. USED IN DUPDISK DTH =* HILO DTH EDN .BYTE 'E:',CR EDH = EDN/256 EDL = (-256)*EDH+EDN .PAGE ; **** DOS MENU ****^ H ; ; DMENU .BYTE CLSCR .BYTE 'DISK OPERATING SYSTEM VERSION 2.0D ',CR .BYTE 'COPYRIGHT 1980 ATARI ',CR,CR .BYTE 'A. DISK DIRECTORY I. FORMAT DISK',CR .BYTE 'B. RUN CARTRIDGE J. DUPLICATE DISK',CR .PAGE .BYTE 'C. COPY FILE K. BINARY SAVE',CR .BYTE 'D. DELETE FILE(S) L. BINARY LOAD',CR .BYTE 'E. RENAME FILE M. RUN AT ADDRESS',CR .BYTE 'F. LOCK FILE  N. CREATE MEM.SAV',CR .PAGE .BYTE 'G. UNLOCK FILE O. DUPLICATE FILE',CR .BYTE 'H. WRITE DOS FILES',CR .BYTE CDN,CDN,CDN,CDN,CDN DMEND =* DULEN = DMEND-DMENU HILO DULEN HILO DMENU ; DUJPT .WORD DIRLST,STCAR,CPYFIL,DELFIL,RENFIL,LKFIL,ULFIL .WORD WBOOT,FMTDSK,DUPDSK,SAVFIL,LDFIL,BRUN,MEMSAV .WORD DUPFIL HILO DUJPT DUNUM = 15 ;NUMBER OF FUNCTIONS .PAGE ; **** DISK OPERATING SYS MONITOR ****^ H ; ; DOSOS LDX #$FF HILO DOSOS CLD ;MAKE SURE DECIMAL MODE OFF STX BRKKEY INX STX LOADFG LDA #2 STA LMARGN LDA #39  STA RMARGN ;SET MARGINS LDA POKMSK ;ENABLE BREAK INTERRRUPTS ORA #$80 STA POKMSK STA IRQEN JSR INITIO ;CLOSE FILES ; ; DISK UTILITY MONITOR ; DSKUTL DU1 LDA #DUNUM STA MENUSZ ;SET MENU SIZE. LDA #DUJPTL STA JMPTBL LDA #DUJPTH STA JMPTBL+1 ;SET UP JUMP TABLE ADDRESS ; FALL THRU TO MENU SELECT ; ; ; ; MENU SELECT MONITOR -- VECTORS TO ROUTINE SELECTED FROM MENU. ; SHMEN LDA #DMENUL ;GET MENU ADDRESS STA ICBAL LDA #DMENUH STA ICBAH LDA #DULENL ;GET MENU LENGTH STA ICBLL LDA #DULENH STA ICBLH JSR DSPMSG ;SHOW MENU ; ; SELECT ITEM FROM MENU .PAGE ; **** FUNCTIONS COME HERE WHEN THEY ARE DONE ****^ H ; MENUSL LDX #$FF ;RESET STACK AT THIS POINT TXS INX STX WCFLAG ;CLEAR WILD-CARD FLAG LDA #SITL ;SELECT ITEM MESSAGE LDX #SITH JSR PRNTMSG LDA #$40 ;MAKE SURE UPPER CASE STA SHFLOK JSR CHRGET ;GO GET KEYBOARD CHAR. ; CMP #CR  ;IF CR REDISPLAY MENU BEQ SHMEN ; SEC SBC #'A ;CONVERT ASCII CHAR. TO BINARY # & SUB 1. BMI RANGE ;IF ASCII CHAR NOT A #, GO READ AGAIN CMP MENUSZ ;IS THE # ENTERED > MENU SIZE?  BPL RANGE ;IF YES, GO READ AGAIN. ASL A TAY ;SET INDEX TO (MENU # - 1) * 2 LDA (JMPTBL),Y INY STA RAMLO ;GET STRING POINTER LDA (JMPTBL),Y STA  RAMLO+1 LDY #1 ;LOAD STRING POINTER INTO REGISTERS LDA (RAMLO),Y ;FOR DSPLIN TAX DEY LDA (RAMLO),Y JSR DSPLIN ;PRINT MODULES INITIAL STRING JSR SCROL ;SCROLL  INPUT WINDOW LDA RAMLO ;INC BY 2 TO POINT PAST STRING POINTER CLC ADC #2 STA RAMLO LDA RAMLO+1 ADC #0 ;CARRY STA RAMLO+1 ;PUT HI BYTE. JMP (RAMLO ) ;JUMP TO ROUTINE SELECTED BY MENU. RANGE LDA #NSIL LDX #NSIH JSR DSPLIN ;NO SUCH ITEM MESSAGE JMP MENUSL .PAGE NSI .BYTE 'NO SUCH ITEM',CR ; ; PROMPT FOR MENU SELECTION OR REDISPLAY MENU - RETURN IS IN INVERSE ; SIT .BYTE 'SELECT ITEM OR ',$D2,$C5,$D4,$D5,$D2,$CE .BYTE ' FOR MENU',CR HILO NSI HILO SIT MNSL = MENUSL HILO MNSL .PAGE ; **** DIRECTORY LISTING ROUTINE ****^ H ; ; DIRLST .WORD DLMG JSR GETIC1 JSR USEBUF ;INIT BUFADR & BUFLEN LDX PTR LDA #CR STA PAR-1,X ;ASSURE GOOD TERM LDA PAR-2,X ;LAST CHAR OF SEARCH SPEC CMP  #': ;IF COLON, ADD *.* BNE GLF LDA #'* STA PAR-1,X STA PAR+1,X LDA #'. STA PAR,X LDA #CR STA PAR+2,X INX INX INX STX PTR GLF STX SAVX LDX #$20 JSR PIOCB JSR GETFIL JSR PERX LDA #6 ;READ DIR INFO LDX #$10 STA ICAX1,X LDA #OPEN ;OPEN STA ICCOM,X STX CSRC ;COPY SOURCE=DIRECTORY INFO CPX #$10 BNE *+3 JSR CIOCL LDA PTR SEC SBC SAVX CMP #3 ;IF ONLY 3 CHARS, IS 'D:'CR, USE DEFAULT  BEQ DLST1 DLST0 JMP PDES ;GO INTO COPY DLST1 LDX SAVX LDA PAR,X CMP #'D BNE DLST0 JMP PDES1 ;GO INTO COPY WITH DES='E:' .PAGE DLMG .BYTE 'DIRECTORY--SEARCH SPEC,LIST FILE?',CR .PAGE ; **** DELETE FILE ROUTINE ****^ H ; ; DELFIL .WORD DEMG JSR GETIC1 JSR PERX ;EXIT IF PARAM ERRORS ; JSR CHKVER ;BE SURE THAT IT IS VER. 2 DISKETTE ; ; CONTINUE WITH DELETE - ALLOW ONLY FOR DISK DEVICE ID ; LDA PAR ;GET DEVICE CMP #'D ;ONLY ALLOW DELETE FOR D: BEQ DF1 LDA #NDFL LDX #NDFH JSR DSPLIN JMP MENUSL NDF .BYTE 'NOT A DISK FILE',CR HILO NDF DF1 LDX #$10 LDA OPT CMP #'N ;IF OPTION=N, NO QUERY BNE DWQ ;NO, DELETE WITH QUERY LDA #DELETE STA ICCOM,X JSR CIOCL  JMP MENUSL DWQ LDA #TYQL LDX #TYQH JSR DSPLIN ;SAY TYPE Y TO DELETE... LDA #0 STA IPTR ;HOW MANY FILES TO SKIP, NONE AT FIRST LDX #$20 ;SET UP DELETE IOCB  LDA #DELETE STA ICCOM,X LDA #DB3L STA ICBAL,X LDA #DB3H STA ICBAH,X LDA #'D STA DBUF-3 LDA #': STA DBUF-1 LDA PAR+1 ;DEVICE NUMBER OR : FROM OP INPUT CMP #': BNE *+4 LDA #'1 STA DBUF-2 ;KLUDGE KLUDGE KLUDGE IDRD LDX #$10 LDA #OPEN STA ICCOM,X LDA #6 STA ICAX1,X ;DIR READ OPEN LDA #PARL STA ICBAL,X LDA #PARH STA ICBAH,X JSR CIOCL LDA #DBUFL STA ICBAL,X LDA #DBUFH STA ICBAH,X LDA #GETREC  STA ICCOM,X LDA #0 STA PTR ;HOW MANY FILES WE HAVE SKIPPED ; READ FILENAME FROM DIR, QUERY AND DELETE RDFN LDX #$10 LDA #0 STA ICBLL,X LDA #1 STA ICBLH,X  JSR CIOCL ;READ A LINE FROM DIRECTORY LDA DBUF+1 ;IF FILE LINE, THIS IS BLANK CMP #' BNE DELX ;THIS IS FREE BLOCKS LINE INC PTR ;COUNT THIS FILE LDA PTR ;HAVE WE SKIPPED ENUF YET CMP IPTR BMI RDFN ;BR IF NO LDX #0 ;PUT PTR LDY #2 ;GET PTR ;MASSAGE DELETE FILE NAMES MDN1 LDA DBUF,Y CMP #' ;END OF FILENAME BEQ MDN2 STA DBUF,X INX INY CPX #8 BMI MDN1 ;FILENAME IS MOVED, PUT .EXT MDN2 LDA #'. STA DBUF,X INX LDY #10 ;WHERE EXT IS MDN3 LDA DBUF,Y  STA DBUF,X INY INX CPY #13 BMI MDN3 STX SAVX ;PUT CR HERE LATER LDA #'? ;FOR QUERY STA DBUF,X INX LDA #CR STA DBUF,X L DA #DB3L LDX #DB3H JSR DSPLIN ;GO ASK ABOUT THIS FILE JSR CHRGET CMP #'Y BNE RDFN ;GO DO NEXT FILENAME LDA PTR ;NUMBER FILES WE HAVE GONE THRU SO FAR ST!A IPTR ;IS NEW NUMBER TO SKIP. LDX SAVX LDA #CR STA DBUF,X LDX #$20 ;DELETE IOCB JSR CIOCL JSR CLOS1 JMP IDRD ;CLOSE AND REOPEN DIR READ FILE DELX " JSR CLOS1 ;CLOSE DIR READ FILE JMP MENUSL CLOS1 LDX #$10 LDA #CLOSE STA ICCOM,X JMP CIOCL ;DO CLOSE AND RETURN TYQ .BYTE 'TYPE ',$22,'Y',$22,' TO DELETE...',CR HILO #TYQ DEMG .BYTE 'DELETE FILE SPEC',CR ;LIST .PAGE ; **** COPY FILE ROUTINE ****^ H ; ; CPMG .BYTE 'COPY--FROM, TO?',CR OE .BYTE 'OPTION NOT ALLOWED',CR HILO OE ; ; ; ; ; WCFLAG *=*+1 WCSKP1 *=*+1 WCSKP2 *=*+1 WCB$UFL = 20 WCBUF *=*+WCBUFL WCOPYM .BYTE ' COPYING---' WCBUF2 .BYTE 'DN:' *=*+WCBUFL-3 CPYFIL .WORD CPMG ;COPY FILE PROMPT JSR GETIC1 ;GET SOURCE DEVICE, ETC. LDA PTR STA SAVX % LDA PAR ;GET 1ST CHAR. OF DEVICE CMP #'D ;TEST IF IT IS THE DISK BNE JMPNWC ;BRANCH IF NOT THE DISK (THEN USE OLD CODE) LDX #0 ;LOOK AT SOURCE FILE SPEC. JSR LOOKWC ;LOO&K FOR WILDCARDS IN FILE SPEC. BEQ CPYFL1 ;BRANCH IF WILDCARDS USED IN DISK SPEC. JMPNWC JMP NOTWC ;USE OLD CODE CPYFL1 LDA #$80 ; ; WCINIT STA WCFLAG ;SET 'WILDCARD' MODE (COPY-FILE OR DUPLICATE-FILE) LDA' #0 STA WCSKP1 ; WCOPYL LDA #0 STA WCSKP2 LDX #$10 ;OPEN DIRECTORY LDA #6 STA ICAX1,X LDA #OPEN STA ICCOM,X LDA #.LOW.PAR STA ICBA(L,X LDA #.HIGH.PAR STA ICBAH,X JSR CIOCL ; ; WCOPYR LDA #GETREC ;READ DIRECTORY STA ICCOM,X LDA #WCBUFL STA ICBLL,X LDA #0 STA ICBLH,X LDA ) #.LOW.WCBUF STA ICBAL,X LDA #.HIGH.WCBUF STA ICBAH,X JSR CIOCL ; LDA WCBUF ;IF 1ST CHAR. OF DIR READ IS A #-IT IS TIME TO QUIT CMP #'0 BCC WCGOT CMP #*': BCS WCGOT ; LDA #CLOSE ;ALL DONE -- NORMAL EXIT OF WILDCARDED COPY STA ICCOM,X JSR CIOCL JMP MENUSL ; ; WCGOT LDA WCSKP1 ;IF ALREADY COPYIED OR SKIPPED THIS ; FILE, THEN IGNORE+ IT AND REREAD DIRECTORY CMP WCSKP2 BEQ SKIP1 ; INC WCSKP2 BNE WCOPYR ; SKIP1 INC WCSKP1 ; LDA #CLOSE ;CLOSE DIRECTORY READ FILE STA ICCOM,X JSR CIOCL ; ; , LDY #2 ;DON'T COPY .SYS FILES SYSLOP LDA WCBUF+10,Y CMP DOTSYS,Y BNE NOSYS DEY BPL SYSLOP BMI WCOPYL ; DOTSYS .BYTE 'SYS' ; NOSYS LDY #'1 ;CALC SOURCE DRIVE N-UMBER LDA PAR+1 CMP #': BEQ WCGOT1 TAY WCGOT1 STY WCBUF2+1 ; ; LDX #2 ;COMPRESS SPACES, ADD ':', ADD 'CR' LDY #3 ; COMPR1 LDA WCBUF,X CMP #' BEQ . COMPR2 STA WCBUF2,Y INY ; COMPR2 INX CPX #10 BNE COMPR1 ; LDA WCBUF,X CMP #' BEQ COMPR5 LDA #'. STA WCBUF2,Y INY COMPR3 LDA WCBUF,X / CMP #' BEQ COMPR4 STA WCBUF2,Y INY COMPR4 INX CPX #13 BNE COMPR3 ; COMPR5 LDA #CR STA WCBUF2,Y ; ; LDA #.LOW.WCOPYM ;PRINT 'COPYING---DEV:FILENAME.EXT' M0SG LDX #.HIGH.WCOPYM JSR DSPLIN ; BIT WCFLAG BVC WCOPY ;BR TO MIDDLE OF DUP FILE ROUTINE IF DUPING FILES ; LDX #$10 ;SET UP BUFR ADDR TO POINT TO WILDCARDED FILENAME LDA 1#.LOW.WCBUF2 STA ICBAL,X LDA #.HIGH.WCBUF2 STA ICBAH,X JMP WCDUPS ; WCOPY JSR USEPGM ;SET BUFFER SIZES LDX #$10 ;OPEN COPY SORCE FILE LDA #OPEN STA ICCOM2,X LDA #4 STA ICAX1,X LDA #.LOW.WCBUF2 STA ICBAL,X LDA #.HIGH.WCBUF2 STA ICBAH,X STX CSRC JSR CIOCL ; LDX #$20 JSR PIOCB ;GET CO3PY DESTINATION FILE LDA PTR ;SAVE PTR,IPTR-MIGHT REPT GET 2ND FILENAME MANY TIMES PHA LDA IPTR PHA JSR GETFIL ;GET 2ND FILE NAME TO PAR PLA ;RECOVER IPTR,PTR 4STA IPTR PLA STA PTR LDX SAVX LDA PAR,X CMP #'D BEQ WCOPY0 JMP PDES ;JUMP TO OLD COPY-FILE CODE IF NOT A DISK DESTINATION ; WCOPY0 LDY #'1 ;CALCULATE D5ESTINATION DRIVE # LDA PAR+1,X CMP #': BEQ WCOPY1 ; TAY WCOPY1 CPY WCBUF2+1 BNE WCOPY2 JSR CLOSX ;CAN NOT COPY TO SAME DRIVE NUMBER -- ERROR & EXIT ; JMP ODMS ; ; 6WCOPY2 LDX #$20 STY WCBUF2+1 ;CHANGE FILESPEC TO DESTINATION LDA #.LOW.WCBUF2 STA ICBAL,X LDA #.HIGH.WCBUF2 STA ICBAH,X JMP OPDES1 ;CONTINUE INTO OLD COPY-FILE CODE ; ; N7OTWC = * LDX #$20 ;IOCB 3 JSR PIOCB JSR GETFIL ;GET SECOND FILENAME ; ; MAKE SURE DESTINATION IS NOT DOS.SYS ; LDX SAVX ;ENTRY-INDEX TO DEST FILE SPEC JSR TSTDOS ;WO8N'T RETURN IF IS DOS.SYS ; LDX SAVX JSR LOOKWC BNE NWCIND ;BRANCH IF NO WILDCARDS IN DESTINATION LDA #NWAL LDX #NWAH JSR DSPLIN JMP MENUSL NWA .BYTE 'WILD CARD9S NOT ALLOWED IN DESTINATION',CR HILO NWA NWCIND = * JSR PERX ;IF PARAM ERRS, EXIT JSR USEPGM ;ASK USER IF CAN USE PGM AREA OR DATA BUFFER PSRC = * LDA PAR ;GET 1ST LETR OF :PARAM CMP #'K BEQ ODMS ;K: GETS 'OPTION DOESNT MAKE SENSE' FOR NOW CMP #'C BEQ ODMS ;C: GETS 'OPTION DOESNOT MAKE SENSE' FOR NOW CMP #'E ;E: AS SOURCE IS SPECIAL BNE ; OPSRC ;IF NO THEN OPEN SOURCE FILE LDX #0 STX CSRC JMP PDES OPSRC CMP #'S BEQ ODMS ;S: AS SOURCE GETS O.D.M.S. FOR NOW ; ; OPEN SOURCE FILE ; LDX #$10 LDA < #OPEN STA ICCOM,X LDA #4 ;OPEN IN STA ICAX1,X STX CSRC CPX #$10 BNE *+33 JSR CIOCL ;OPEN SOURCE FILE HERE ; ; READY FOR OPEN OF DESTINATION ; PDES = LDX SAVX LDA PAR,X ; CMP #'K ;IS DEST KEYBOARD? BEQ ODMS ;YES, THEN CAN'T DO IT ; CMP #'E ;CHECK FOR SPECIAL CASE BNE OPDES ;IF NOT PDES1 LDA #0 ;SPE>CIAL CASE - DONT OPEN, USE EXISTING IOCB STA CDES JMP DOCPY ODMS LDA #OEL LDX #OEH ;SAY OPTION NOT ALLOWED JSR DSPLIN JSR CLOSX ;CLOSE IOCB 1 & 2 JMP MENUSL ; OPDE?S CMP #'C BEQ ODMS ;C: GETS 'OPTION DOESNOT MAKE SENSE' FOR NOW LDX OPT ;GET 2ND FILE OPTION ; CPX #'A ;APPEND TO DISK FILE BNE OPDES1 CMP #'D BNE ODMS @ LDA #9 BNE OPDES3 OPDES1 LDA #8 OPDES3 LDX #$20 STA ICAX1,X ;OPEN TYPE OUT LDA #OPEN STA ICCOM,X ;OPEN STX CDES JSR CIOCL LDA #0 STA A ICAX2,X ;COPY FROM CSRC TO CDES DOCPY LDA #GETCHR GC1 LDX CSRC LDY CDES STA ICCOM,X LDA #PUTCHR STA ICCOM,Y LDA BUFADR ;ADDRESS OF BUFFER - EITHER STA ICBAL,X B;PGM AREA (MEMLO) OR DATA BUFFER (DBUF) STA ICBAL,Y LDA BUFADR+1 ;BUFADR IN LSB,MSB ORDER STA ICBAH,X STA ICBAH,Y CLOOP LDX CSRC LDA BUFLEN ;LENGTH OF BUFFER ADDRESSED STA C ICBLL,X ;BY BUFADR LDA BUFLEN+1 ;BOTH BUFADR & BUFLEN ARE ASSIGNED STA ICBLH,X ;IN SUBROUTINE USEPGM JSR CIO ;READ FROM INPUT STY SSTAT LDX CDES LDY CSRC LDDA ICBLL,Y STA ICBLL,X LDA ICBLH,Y STA ICBLH,X ORA ICBLL,Y ;IF SOURCE FILE LENGTH = 0 BEQ CKRS ;DONT DO WRITE JSR CIOCL ;WRITE, ABORT IF ERROR CKRS LDA SSTAET ;GET READ OPERATION STATUS BACK BPL CLOOP ;IF OK, GO READ SOME MORE CMP #$88 ;EOF STATUS BEQ *+5 JMP CIOER ;IF NOT, ABORT CLOC LDX CSRC BEQ DU4 ;IF E:, DONTF CLOSE ; ;CLOSE SOURCE FILE ; LDA #CLOSE STA ICCOM,X JSR CIO DU4 LDX CDES BEQ DU3 ;IF DES=E: LDA #CLOSE STA ICCOM,X JSR CIO DU3 LDX CDES BGNE DU6 LDA #.LOW.DDSK+1 LDX #.HIGH.(DDSK+1) JSR PRNTMSG ;PRINT A CR BEFORE SELECT OR WILDCARD PROMPT DU6 = * ; BIT WCFLAG BPL DU5 JMP WCOPYL ;BRANCH BACK TO WILHD CARD LOOP DU5 JMP MENUSL .PAGE ; **** RENAME FILE ROUTINE ****^ H ; ; ; RENAME SETS UP IOCB #1 WITH THE OLD FILE NAME AND THE BUFFER ADDRESS ; POINTS TO THE NEW FILE NAME. THE NEW FILE SPECIFICATION CANNOT HAVE ; A DEVICE ID. THEI DEVICE ID IS THE SAME AS SPECIFIED FOR THE OLD FILE ; EG D2:ABC.S2,QQQ.R3 THIS RENAMES ABC.S2 ON DRIVE #2 TO QQQ.R3 ; ; RENFIL .WORD RNMG JSR GETIC1 ;GET OLD FILE SPEC & PUT ADDR IN IOCB JSR GETNAME ;GET NEW FILE NAMJE JSR PERX ;EXIT IF PARAMETER ERRORS ; JSR CHKVER ;MAKE SURE VER 2 DISKETTE ; ; CONTINUE WITH RENAME ; LDA #RENAME LDX #$10 STA ICCOM,X JSR CIOCL JMP MENKUSL RNMG .BYTE 'RENAME - GIVE OLD NAME, NEW',CR ; ;******************* SUBROUTINE ******************* ; ; MAKE SURE THIS IS A VERSION 2 FORMAT DISK ; CHKVER LDY #1 ;ASSUME DRIVE 1- GET DRIVE # LDA PAR+1 ;TESTL CHAR 2 OF FILE SPEC FOR SEMICOLON CMP #': ;IF IS, USING DEFAULT DRIVE (1) BEQ DRV1 ;IT IS, SO SAVE DRIVE # AND #$0F ;ELSE CHAR 2 IS ASCII REP OF DRIVE # TAY ;CONVERT TO BINARMY & SAVE IT DRV1 STY UNNO ;SAVE DRIVE # ; JMP TSTVER2 ;TEST FOR VER 2 DISK- WON'T RETURN IF NOT ; .PAGE ; **** FORMAT DISK ROUTINE ****^ H ; ; FMTDSK .WORD WHD JSR GETLIN JSR GETDN N CLC ADC #'0 STA DDSK STA CDSK JSR PERX LDA #VFML ;QUERY TO VERIFY DRIVE NUMBER LDX #VFMH JSR DSPLIN JSR CHRGET CMP #'Y ;SEE IF OKO BNE FMX LDA #FDPL LDX #$10 STA ICBAL,X LDA #FDPH STA ICBAH,X LDA #FORMAT STA ICCOM,X JSR CIOCL ;CALL CIO TO DO FORMAT FMX JMP MENUSPL ;EXIT. WHD .BYTE 'WHICH DRIVE TO FORMAT?',CR VFM .BYTE 'TYPE ',$22,'Y',$22,' TO FORMAT DISK ' DDSK *=*+1 .BYTE CR FDP .BYTE 'D' CDSK *=*+1 .BYTE ':',CR HILO WHD HILO VFM HILQO FDP .PAGE ; **** START CARTRIDGE ROUTINE ****^ H ; ; SYVBL = SYSVBV HILO SYVBL XTVBL = XITVBV HILO XTVBL STCAR .WORD SCMG ;NO MSG, PRINT A ROMTST = $BFFD LDY ROMTSRT ;TEST IF RAM OR OTHER LDA #$AA ;PATTERN #1 STA ROMTST CMP ROMTST BNE NOTRAM ;BRANCH IF NOT RAM LDA #$55 ;PATTERN #2 STA ROMTST CMP ROMTST BSNE NOTRAM ;BRANCH IF NOT RAM ; STY ROMTST ;THERE IS VALID RAM - SAY NO CART NOCART LDA #NCAL LDX #NCAH ;SAY NO CART JSR DSPLIN JMP MENUSL ; ; CHECK IF ROM OR EMPTY ADDRESS SPACET ; NOTRAM LDA $BFFC ;KNOWN ROM ZERO BYTE BNE NOCART ;BRANCH IF EMPTY ADDRESS SPACE ; TAX ;SINCE EMPTY ADDRESS SPACE GIVES A RANDOM CKCART LDA ROMTST ;VALUE, TEST THE SAME LOCATION MANY TIMES. U BEQ NOCART ;BRANCH IF NO CARTRIDGE CMP ROMTST BNE NOCART ;BRANCH IF NO CARTRIDGE INX BNE CKCART ;LOOP BACK ; ; ; RESET VERTICAL BLANK VECTORS BEFORE ENTERING CART ; JSR IVNITIO LDA #6 SET VVBLKI LDX #SYVBLH HI BYTE LDY #SYVBLL JSR SETVBV LDA #7 ;SET VVBLKD LDX #XTVBLH LDY #XTVBLL JSR SETVBV JMWP CLMJMP .PAGE NCA .BYTE 'NO CARTRIDGE' SCMG .BYTE CR HILO NCA ; ; ; ******* RUN AT ADDRESS *******^ H ; ; ; BRUN .WORD BRMG JSR GETLIN JSR GETNO JSR PERX STA XRAMLO STX RAMLO+1 LDA CTR CMP #4 BEQ MOUT1 ;RETURN TO MENU IF NO RUN ADDRESS GIVEN JSR INITIO ;CLOSE ALL IOCB'S, THEN REOPEN S/E JMP LMTR ;LOAD MEM.SAV & JUMP TO ADDRYESS ; ; BRMG .BYTE 'RUN FROM WHAT ADDRESS?',CR .PAGE ; **** CREATE MEM.SAV FILE ON DISK ****^ H ; ; MEMS .BYTE 'TYPE ',$22,'Y',$22,' TO CREATE MEM.SAV',CR MEMSAV .WORD MEMS JSR CHRGET ; GET CHAR (CR) CZMP #'Y BNE MOUT ;BRANCH IF USER'S ANSWER NOT A Y JSR MEMSVQ ;TRY TO OPEN MEM.SAV BMI MCONT ; IF FILE DOESN'T EXIST THEN JUMP LDA #MEMSGL ; ELSE 'MEMORY.SAVE' AREADY EXIST LDX [ #MEMSGH ; JSR DSPLIN ; DISPLAY THIS FACT MOUT JSR CLOSX ; EXIT AFTER CLOSING IOCB1 MOUT1 JMP MENUSL ; ; ; WRITE MEMORY.SAVE TO DISK ; MCONT JSR MWRITE ; WRITE FILE BPL MOUT MERR JMP \ CIOER1 ; DISPLAY ERROR ; MEMSG .BYTE 'MEM.SAV FILE ALREADY EXISTS',CR HILO MEMSG .PAGE ; **** WRITE DOS & DUP ****^ H ; ; WBOOT .WORD DOSDRV ;ADDRESS OF DRIVE # PROMPT ; ; RETREIVE DRIVE NUMBER FROM USER]. ; JSR GETLIN ;GET INPUT JSR GETDN ;GET DRIVE AS NUMBER, VERIFY IT JSR PERX ;EXIT IF ERROR STA UNNO ;SAVE IT FOR TSTVER2 ORA #'0 ;TURN BACK TO ASCII REP STA^ DS+1 ;STORE IN DOS.SYS FILE SPEC STA QWMG+31 ;& IN PROMPT ; JSR TSTVER2 ;TEST IF VERSION 2 DISK - IF ISN'T WON'T RETURN ; ; ASK USER IF CAN WRITE DOS & DUP TO SPECIFIED DRIVE ; LDA #QWMGL ;P_RINT PROMPT LDX #QWMGH JSR DSPLIN JSR CHRGET CMP #'Y BNE WBX ;EXIT UNLESS Y ; ; TELL USER WRITING DOS FILES AND WRITE DOS.SYS FIRST- JUST OPEN IT. ; LDA #WBMGL ` LDX #WBMGH JSR DSPLIN ; LDA #OPEN LDX #$10 ;OPEN DOS.SYS ON IOCB #1 STA ICCOM,X ;WILL CAUSE FMS TO REWRITE BOOT SECTOR LDA #DSL ;& A COPY OF DOS.SYS STA ICBAL,X a LDA #DSH STA ICBAH,X LDA #8 STA ICAX1,X JSR CIOCL ;DO OPEN, IF ERROR GOTO MENU ; LDX #$10 LDA #CLOSE STA ICCOM,X JSR CIOCL ;DONE CLOSE bIT. ; ; WRITE DUP.SYS - SWAP AREA FILE ; LDX #11 ;MOVE 11 CHARS MDUPBL LDA DUPSYS-1,X STA PAR-1,X ;MOVE FILE NAME TO PARAMETER LIST DEX BNE MDUPBL LDA DS+1 ;GET DRIVE NUMcBER STA PAR+1 ;PUT IT IN DUP.SYS FILE SPEC ; STX PTR LDX #$10 JSR PIOCB ;PUT FILE NAME POINTER IN IOCB LDA #DTHL STA LDST LDA #DTHH STA LDST+1 d LDA #.LOW.NMDUP STA LDND LDA #LENL STA WDRL+1 LDA #LENH STA WDRH+1 LDA #.HIGH.NMDUP STA LDND+1 PHA ;NO /A LDA #.LOW.DOSOS e STA RUNAD LDA #.HIGH.DOSOS STA RUNAD+1 ;SET DUP.SYS RUN ADDRESS DEC RUNQ+1 ;SET RUN FLAG JMP NRUNAD ;WRITE DUP.SYS WBX JMP MENUSL DOSDRV .BYTE 'DRIVE TO WRITE DOS FILES TO?',CfR WBMG .BYTE 'WRITING NEW DOS FILES',CR HILO WBMG .PAGE QWMG .BYTE 'TYPE ',$22,'Y',$22,' TO WRITE DOS TO DRIVE .',CR HILO QWMG DS .BYTE 'D1:DOS.SYS',CR HILO DS WVD .BYTE 'ERROR - NOT VERSIgON 2 FORMAT.',CR HILO WVD .PAGE ; **** TEST FOR VERSION 2 FORMAT - SUBROUTINE ****^ H ; ; ; ; SUBROUTINE - TSTVER2 ; ; READS THE DISK'S VTOC AND CHECKS IF VERSION BYTE IS SET AS 2. ; ; ENTRY - DRIVE # STOREDh IN UNNO ; EXIT - RETURNS ONLY IF IS A VERSION 2 DISK ; ELSE DOES AN ERROR EXIT BACK TO MENU ; CALLS - DRVSTAT AND RVTOC ; CALLED BY - DELFIL, RENFIL, WBOOT. ; ; ; GET DRIVE TYPE SO iKNOW CORRECT SECTOR SIZE - NEEDED FOR RVTOC ; TSTVER2 = * LDY #0 ;GET DRIVE TYPE IN BUFL STY SECSIZ ;ASSUME 256 - NEEDED BY RVTOC INY STY SECSIZ+1 LDA UNNO ;GET DRIVE # j JSR DRVSTAT ;FIND OUT TYPE - CARRY FLAG BCS OKTYP ;BRANCH IF 256 TYPE LDA #$80 ;ELSE SET AS 128 BYTE DEVICE STA SECSIZ LSR SECSIZ+1 ;CHANGE HI BYTE FROM 01 TO 00 ; ; READ THE kVTOC & CHECK IF VERSION 2 ; OKTYP JSR RVTOC ;READ IN VTOC TO DBUF LDA DBUF ;1ST BYTE IS VERSION # CMP #2 ;IS IT VERSION 2? BEQ SMVRS ;YES, SAME VERSION - RETURN ; ; NOT A VERSION 2 lDISK - PRINT MSG & GOTO MENU ; LDA #WVDL ;ELSE, NOT SAME VERSION LDX #WVDH ;PRINT INCOMPATIBLE MSG JSR DSPLIN ; JMP MENUSL ;GOTO MENU ; ; DISK IS VERSION TWO SO RETURN ; SMVRS RTSm ;RETURN .PAGE ; **** LOAD USER FILE FUNCTION ****^ H ; ; LDFIL .WORD LFMG JSR GETIC1 LDA #0 LDX OPT STA OPT CPX #'N ;IS OPTION N FOR DON'T LOAD AND GO? n BNE NOTN ;BRANCH IF NOT DEC OPT NOTN JSR PERX JSR LOAD CPX #0 ;PROCESS LOAD SUBR RESPONSE BEQ LDFX ;BRANCH IF LOAD WAS OK CPX #3 BEQ NLF o ;IF BAD LOAD FILE TYA ;OTHERWISE WE GOT A CIO ERROR JMP CIOER ;GO SAY WHAT IT IS NLF LDA #BLFL LDX #BLFH JSR DSPLIN ;BAD LOAD FILE MSG JSR CLOSX ;CLOSE THE FIpLE LDFX JMP MENUSL ;EXIT BLF .BYTE 'BAD LOAD FILE',CR HILO BLF LFMG .BYTE 'LOAD FROM WHAT FILE?',CR .PAGE ; **** LOCK & UNLOCK FILE COMMANDS ****^ H ; ; LKFIL .WORD LKMG ;DO LOCK JSR qGETIC1 JSR PERX LDA #LOCK LDX #$10 STA ICCOM,X JSR CIOCL JMP MENUSL LKMG .BYTE 'WHAT FILE TO LOCK?',CR ; ULFIL .WORD ULMG ;DO UNLOCK JSR GETIC1 JSrR PERX LDA #UNLOCK LDX #$10 STA ICCOM,X JSR CIOCL JMP MENUSL ULMG .BYTE 'WHAT FILE TO UNLOCK?',CR .PAGE ; **** DUPLICATE DISK ROUTINE ****^ H ; ; DDMG .BYTE 'DUP DISKs-SOURCE,DEST DRIVES?',CR OK .BYTE 'TYPE ',$22,'Y',$22,' IF OK TO USE PROGRAM AREA',CR HILO OK CMSI .BYTE 'CAUTION: A ',$22,'Y',$22,' INVALIDATES MEM.SAV.',CR HILO CMSI ; ; RVTOC READS VOLUME TABLE OF CONTENTS SECTtOR ; RVTOC LDA #1 STA DSHI ;READ VTOC SECTOR LDA #$68 STA DSLO JSR SETBUFL ;SET BUFL FOR RSEC1 LDA #DBUFH STA DBUFHI LDA #DBUFL STA DBUFLO u ;POINT DCB AT DBUF JSR RSEC1 LDA #0 STA PTR LDA DBUF+$A STA CSRC ;BYTE OF ALLOC MAP LDA #8 STA IPTR ;COUNT BITS IN BYTE LDA #0 STA DvSHI ;POINT TO SECTOR ONE LDA #1 STA DSLO RTS ; ; DUPDSK .WORD DDMG LDA #0 ;ASSUME SINGLE DRIVE STA TWODRV ;CLEAR FLAG JSR GETLIN JSR GETDN STA w UNNO ;UNIT NO FOR READ JSR GETDN STA CDES ;CDES IS THE DEST DRIVE # JSR PERX ; ; DETERMINE THE DRIVE TYPES OF THE SOURCE AND DESTINATION DRIVES ; IF THEY ARE NOT THE SAME THEN ERROR - PRINT xMSG AND GOTO MENU. ; IF THEY ARE THE SAME THEN SET SECSIZ AS LENGTH OF NON-BOOT ; SECTORS OF DEVICE- USED IN SETBUFL. ; LDA #$80 ;ASSUME SOURCE IS 128 BYTE/SECTOR STA SECSIZ ;SECSIZ IN LSB,MSB ORDER yLDA #0 STA SECSIZ+1 ; LDA UNNO ;CHECK SOURCE FIRST, DO STATUS TEST JSR DRVSTAT ;SETS CARRY IF 256, 128 THEN CARRY CLR BCC ONE28 ;BRANCH IF 128 DEVICE LDX #0 ;ELSE SET zSECSIZ AS 256 BYTES STX SECSIZ INX STX SECSIZ+1 ; ; CHECK STATUS ON DESTINATION AND SEE IF COMPATIBLE ; ONE28 LDA CDES ;DO STAUS ON DEST JSR DRVSTAT BCC IS128 ;128,YES TEST F{OR 128 IN SECSIZ BIT SECSIZ ;ELSE CHK FOR 256 IN SECSIZ BPL SAME ;BRANCH IF DES & SRC ARE 256 ; ; NOT THE SAME THEN PRINT MSG AND GOTO MENU. ; INCOMP LDA #NCDRL ;PRINT INCOMPATIBLE DRIVE LDX #|NCDRH ;MSG JSR DSPLIN JMP MENUSL ;GOTO MENU ; ; 128 BYTE CHECK ; IS128 BIT SECSIZ ;IF LSB NOT 80 HEX THEN 256 SRC BPL INCOMP ;AND THEN INCOMPATIBLE ; ; CHECK IF TWO DRIVE OR SINGLE DR}IVE DUP ; SAME LDA UNNO CMP CDES ;IF BOTH UNITS THE SAME BEQ SDD ;SINGLE DRIVE DUP LDX #IBDH LDA #IBDL JSR DSPLIN ;PROMPT TO INSERT BOTH DISKS JSR CHRGET ~ DEC TWODRV ;SET TWO DRIVE FLAG BMI DODKDP ;GO DUP DISK .PAGE IBD .BYTE 'INSERT BOTH DISKS, TYPE RETURN',CR HILO IBD NCDR .BYTE 'ERROR - DRIVES INCOMPATIBLE.',CR HILO NCDR ; ; ;USED BY BOTH SINGLE & DOUBLE DRIVE DUP. WILL NOT ASK TO SWAP IF 2 DRIVE ;FLAG (TWODRV) IS SET. ;IF THE TWO DRIVE FLAG IS CLEAR WILL ;FILL FROM SOURCE DISK, SWAP, EMPTY, SWAP, REPEAT. ; SDD LDA #ISDL ;TELL USER TO INSERT SOURCE LDX #ISDH ;FOR INITIAL READ - USED ONLY FOR SINGLE JSR DSPLIN ;DRIVE DUPLICATE JSR CHRGET DODKDP LDA #NMDUPL ;SET BUFFER AT END OF DUP STA STVEC LDA #NMDUPH STA STVEC+1 ; ; BUFFER BOTTOM MOVES FROM NMDUP TO MEMTOP ; SET END OF BUFFER TO MEMTOP MINUS 1 SECTOR IN BYTES. ; WHEN BUFFER BOTTOM IS LESS THAN OR EQUAL TO BUFFER END, AT ; LEAST ONE MORE SECTOR WILL FIT IN MEMORY. ; LDA MEMTOP ;SECSIZ IS LENGTH OF NON-BOOT SECTORS FOR DEVICE SEC SBC SECSIZ ;T1 IS END OF BUFFER STA T1 LDA MEMTOP+1 SBC SECSIZ+1 STA T1+1 ;T1 IS MEMTOP MINUS SECTOR SIZE. ; ;SEE IF ROOM FOR AT LEAST ONE SECTOR! ; LDA T1 ;DO DOUBLE PRECISION TEST CMP STVEC ;TO SEE IF ROOM LDA T1+1 ;IF T1 IS = STVEC THEN ENUF ROOM SBC STVEC+1 ;FOR ONE SECTOR BCS ENUF ;BRANCH IF (T1)>=(STVEC) NORM LDA #NRML LDX #NRMH JSR DSPLIN JMP MENUSL ; ENUF JSR CKMEM ;SEE IF OK TO USE USER AREA LDA #0 STA OPT ;SET UP FOR READ HERE FIRST PASS JSR RVTOC ;READ VTOC LDA DSLO ;COPY INITIAL WRITE POINTERS STA SWDP ;TO INITIAL READ POINTERS LDA DSHI STA SWDP+1 LDA PTR STA SWDP+2 LDA IPTR STA SWDP+3 LDA CSRC STA SWDP+4 JMP LRS1 ;SKIP FIRST READ PROMPT ; ;READ FROM SOURCE DISK TIL BUF FULL OR END OF DATA. ; DORD LDA #0 ;FLAG WE ARE READING STA OPT BIT TWODRV ;TEST FOR 2 DRIVES BMI LRS1 ;YES, SKIP THE SWAP LDA #ISDL ;INSERT SRC DISK LDX #ISDH XBLK JSR DSPLIN JSR CHRGET ; ;SWAP POINTERS TO WHERE WE ARE ; LRS1 JSR DOSWDP ;SWAP SECTOR AND BITMAP POINTERS ; ;LOOP READING/WRITING SECTORS TO BUFFER AREA ; LRS JSR SETBUFL ;SET BUFL TO LENGTH OF THIS SECTOR JSR AAM ;ADVANCE ALLOCATION MAP BMI ASPT ;IF FREE, ADV SECTOR POINTER AND TRY AGIN BIT OPT ;SEE WHAT MODE BMI DOW ;BR IF WRITE JSR RSEC1 ;DO READ JMP IOD DOW JSR DKWRT ;DO WRITE IOD LDA DBUFLO ;ADVANCE BUFFER POINTER CLC ADC BUFL ;ADD SECTOR SIZE TO BOTTOM OF BUFFER STA DBUFLO ;SO POINT TO NEXT FREE BLOCK LDA DBUFHI ADC BUFL+1 ;BUFL IS LENGTH OF CURRENT SECTOR STA DBUFHI ASPT JSR ASP ;GO ADVANCE SECTOR POINTER BEQ STDD1 ;ALL SECTORS DONE, SWAP TO DEST DISK LDA T1 ;SEE IF ROOM FOR ANOTHER CMP DBUFLO ;SECTOR BELOW MEMTOP LDA T1+1 SBC DBUFHI BCS LRS ;BRANCH IF (DBUF)<=(T1) - ROOM FOR MORE. ; ;SWAP DISKS AND CONTINUE ; STDD LDA OPT BMI DORD ;IF WAS WRITE, GO READ STDD2 DEC OPT ;CHANGE TO WRITE BIT TWODRV ;ARE 2 DRIVES BEING USED? BMI  LRS1 ;YES, SKIP THE SWAP LDA #IDDL ;INSERT DEST DISK LDX #IDDH JMP XBLK ;GO DO WRITE STDD1 LDA OPT ;END OF DATA BPL STDD2 ;IF READ GO WRITE JMP MENUSL ;IF WRITE WE ARE DONE ; ;DOSWDP - EXCHANGE CURRENT AND SAVED BITMAP&SECTOR POINTERS ; ALSO INIT BUFFER POINTER ; DOSWDP LDY #4 SWLOP LDA SWATL,Y STA RAMLO LDA SWATH,Y STA RAMLO+1 ;GET ADDRESS FROM TABLE TO RAMLO LDX #0 LDA (RAMLO,X) ;GET WHATS THERE PHA LDA SWDP,Y STA (RAMLO,X) PLA STA SWDP,Y DEY BPL SWLOP LDA STVEC STA DBUFLO LDA STVEC+1 STA DBUFHI RTS ; ; WHAT A MESS ; HILO DSLO HILO DSHI HILO PTR HILO IPTR HILO CSRC .PAGE SWATL .BYTE DSLOL,DSHIL,PTRL,IPTRL,CSRCL SWATH .BYTE DSLOH,DSHIH,PTRH,IPTRH,CSRCH ; ; NRM .BYTE 'NOT ENOUGH ROOM',CR ISD .BYTE 'INSERT SOURCE DISK,TYPE RETURN',CR IDD .BYTE 'INSERT DESTINATION DISK,TYPE RETURN',CR HILO NRM HILO ISD HILO IDD ; ; ; AAM - ADVANCE ALLOCATION MAP ONE BIT. ; RETURN MINUS IF FREE. ; AAM ASL CSRC ;NEXT BIT OF ALLOC MAP DEC IPTR BNE CBIT ;IF DONE WITH THIS BYTE INC PTR ;GET NEXT ONE LDX PTR LDA DBUF+$A,X ;VTOC IS AT DBUF & BIT MAP STARTS IN 10TH BYTE STA CSRC LDA #8 STA IPTR CBIT LDA CSRC ;CHECK THE BIT RTS ; ; ; ASP - ADVANCE SECTOR POINTER IN DCB. ; RETURN EQ IF AT END. ASP LDA DSLO ;SEE IF END CMP #208 BNE NXS LDA DSHI CMP #2 BEQ ASPX ;ALL DONE NXS INC DSLO BNE ASPX INC DSHI ASPX RTS ; ; RSEC1 - READ A SECTOR WHOSE NUMBER IS IN DCB ; RSEC1 LDA UNNO STA DUNIT CLC ;TELL DISK HANDLER DOING A GET SECTOR PHP ;SAVE FLAG JMP CLDKH ; ; DKWRT - WRITE A SECTOR ; DKWRT LDA CDES ;PUT DEST UNIT # STA DUNIT ;IN DCB SEC ;TELL DISK HANDLER DOING WRITE SECTOR PHP ;SAVE FLAG CLDKH LDA #2 ;SET RETRY COUNT STA RCNT CLD1 LDX #1 ;SET DRIVE TYPE- ASSUME 128 BIT BUFL ;TEST FOR 128 BMI NOT256 ;IF IS BRANCH INX ;ELSE SET FOR 256 NOT256 PLP PHP ;SET ACTION FLAG & SAVE IT FOR RETRY JSR BSIOR ;GOTO FMS DISK HANDLER BPL DRTS ;RETURN IF GOOD STATUS ; DEC RCNT ;ELSE SEE IF MORE RETRIES BPL CLD1 ;YES, DO AGAIN JMP CIOER1 ;CIO ERROR, GO SAY WHICH DRTS PLP ;EVEN OUT STACK  RTS ;RETURN ; ; CKMEM - ASK IF OK TO USE USER AREA ; CKMEM LDA WARMST ;IF MEMORY WAS INTACT BEQ CPTR1 ;QUERY TO BOMB IT LDA #OKL LDX #OKH ;PRINT PROMPT JSR DSPLIN LDA #CMSIL ;PRINT CAUTION MSG LDX #CMSIH ;Y RESPONSE WILL INVALIDATE MEM.SAV JSR DSPLIN JSR CHRGET CMP #'Y ;TEST FOR OK TO BOMB USER AREA BNE DDXT ;IF SAY NO THEN DON'T DO DUP LDA #0 STA WARMST ;TELL CART NO GOOD USER MEMORY STA MEMFLG ;TELL LOADER NO GOOD MEM.SAV CPTR1 RTS ; DDXT PLA ;POP RETURN ADDRESS PLA JMP MENUSL ;GOTO MENU, DON'T DO DUP ; ; ; DRVSTAT - SUBROUTINE TO DO STATUS ON DISK DRIVE SPECIFIED ; BY THE NUMBER IN REG. A. ; RETURNS - CARRY SET = DEVICE HAS 256 BYTE SECTORS ; CARRY CLR = DEVICE HAS 128 BYTE SECTORS ; DRVSTAT STA DUNIT ;STORE UNIT NUMBER IN DCB LDA #STAREQ ;STORE STATUS COMMAND IN DCB STA DCOMND LDA #2 ;SET RETRY COUNT STA RCNT DOSTAT JSR DKHND ;DO STATUS WITH OS HANDLER  BPL CHKTYP ;IF GOOD RETURN, DETERMINE TYPE ; DEC RCNT ;ELSE SEE IF ANOTHER RETRY BPL DOSTAT ;YES, DO AGAIN JMP CIOER1 ;ELSE ERROR EXIT ; CHKTYP CLC ;ASSUME 128 BYTE DEVICE LDA DVSTAT ;GET COMMAND STATUS BYTE AND #$20 ;MASK FOR DRIVE TYPE BIT- D5 BEQ RETSTAT ;128 IF = 0 SEC ;256 IF = 1 RETSTAT RTS ; ; SUBROUTINE - SETBUFL ; ; DETERMINE IF THE CURRENT SECTOR IS A BOOT SECTOR. IF IS USE 128 AS ; SECTOR SIZE, ELSE USE DEVICE SECTOR SIZE STORED IN SECSIZ. ; SETBUFL LDX #$80 ;ASSUME IS BOOT SECTOR LDY #0 ;BUFL IS LSB,MSB ORDER ; LDA DSHI ;TEST IF SECTOR # IS LES THAN 4-BOOT BNE LARGER ;IF HI BYTE NOT ZERO THEN USE DEVICE SECTOR SIZE LDA DSLO ;ELSE TEST LOW BYTE FOR LESS THAN 4 CMP #4 ; BCC SETSIZ ;IF LESS THEN USE BOOT SIZE-128 ; LARGER LDX SECSIZ ;ELSE USE DEVICE SECTOR SIZE LDY SECSIZ+1 ; SETSIZ STX BUFL ;SAVE DATA MOVE LENGTH STY BUFL+1 RTS ; **** DUPLICATE FILE COMMAND ****^ H ; ; ; DUPLICATE FILE FROM ONE DISK TO ANOTHER ;USING ONE DRIVE. FILENAME FOR DUPLICATE FILE IS SAME AS ;SOURCE NAME. USER CAN ENTER ONLY THE SOURCE FILE SPECIFICATION. ;USER HAS OPTION OF USING PROGRAM AREA FOR COPY OR A 250 BYTE ;DATA BUFFER TO GET PROGRAM AREA USER MUST RESPOND WITH ;'Y' AS 1ST CHAR OR THEY WILL GET THE DATA BUFFER. WILL DUPLICATE ;FILE OF ANY SIZE. IF ERROR, PRINTS MSG, CLOSES FILE(S) OPEN AND ;RETURNS TO MENU. TO PREVENT POSSIBLE DAMAGE TO DESTINATION ;DISK, FILE IS OPENED AND CLOSED FOR EACH WRITE. ;MAKES BUFFER LENGTH AN EVEN MULTIPLE OF 125. THIS PREVENTS FRAGMENTATION ;OF THE FILE DUE TO THE APPEND OPEN FUNCTION. 125 IS USED BECAUSE IT IS THE ;SIZE OF DATA PORTION IN A SECTOR. IF THIS CHANGES THE VALUE IN THE PGM ;MUST BE CHANGED. ; KEITH BALL 5/7/80 ; DPFM .BYTE 'NAME OF FILE TO MOVE?',CR ; DUPFIL .WORD DPFM ;DUPLICATE FILE PROMPT JSR GETIC1 ;GET FILENAME TO DUPLICATE ON SAME DRIVE JSR PERX ;DON'T COME BACK IF PARAMETER ERRORS LDA  PAR CMP #'D ;DUPLICATE FILE ONLY FOR DISK DEVICE BEQ ISDISK JMP ODMS ;IF NOT -- SAY CANNOT DO & EXIT ; ISDISK JSR USEPGM ;ASK USER IF TO USE PROGRAM AREA OR BUFFER ; ; HAVE USER INSERT SOURCE FILE AND HIT WHEN DONE ; LDX #ISDH ;ARG: LINE TO BE DISPLAYED ADDR LDA #ISDL ;IN REG. A & X JSR DSPLIN ;PRINT INSERT SOURCE MSG JSR GETLIN ;GOTO SCREEN & WAIT FOR JSR  PERX ;GOTO MENU IF BREAK KEY HIT ; JSR LOOKWC ;SEE IF FILE SPEC. USES WILDCARDS BNE NOWC ;BRANCH IF NO WILD CARDS USED - USE OLD ROUTINE LDA #$40 ;SET 'DUPLICATE WILDCARD' MODE JMP WCINIT ;OPEN WILDCARD DIRECTORY FILE, ETC. ; NOWC = * ; ; MAKE SURE DEST NOT DOS.SYS ; LDX #0 ;ENTRY-INDEX TO FIRST CHAR OF FILE NAME JSR TSTDOS ;WON'T RETURN IF IS DOS.SYS ; ; OPEN SOURCE FILE - ADDR OF FILENAME STRING IN PARAM LIST IS ; ALREADY ASSIGNED TO IOCBB # 2 ; WCDUPS LDX #$10 ;USE IOCB #2 LDA #OPEN ;OPEN COMMAND STA ICCOM,X LDA #4 ;READ ONLY STA ICAX1,X JSR  CIOCL ;CALL CIO - IF ERR PRNT MSG,CLOSE, GOTO MENU ; ; EOFFLG - SOURCE FILE EOF FLAG FTRF - FLAG TO SHOW IF 1ST TIME SOURCE ; FILE WAS READ ; LDA #0 STA EOFFLG ;CLEAR EOF FLAG STA FTRF ;CLEAR MEANS FIRST TIME ; ; DO UNTIL (SOURCE EOF FLAG(EOFFLG) IS SET) ; SET UP IOCB#2 TO DO GET CHAR. ZP LOC BUFADR HAS BUFFER ADDRESS ; BUFLEN HAS BUFFER LENGTH ; DODUP LDX #$10 ;USE IOCB #2 LDA BUFADR ;IN LSB,MSB ORDER  STA ICBAL,X ;SET BUFFER ^AADDR IN IOCB #2 LDA BUFADR+1 STA ICBAH,X LDA BUFLEN ;IN LSB,MSB ORDER STA ICBLL,X ;STORE BUFFER LENGTH LDA BUFLEN+1 ;IN IOCBB #2 STA ICBLH,X LDA #GETCHR ;COMMAND TO GET CHAR - IGNORE EOL'S (9B) STA ICCOM,X JSR CIO ;CALL CIO ; ; CHECK FOR ENDFILE. IF YES, THEN SET FLAG. CHECK FOR ERROR. IF ERR ; THEN PRINT MSG, CLOSE FILE, AND RETURN TO MENU. ; BPL INSDES ;IF GOOD READ WRITE BUFFER CPY #EOF ;WAS IT EOF? BEQ SETFLG ;YES, THEN SET FLAG JMP CIOER1 ;WAS ERR - PRINT MSG,CLOSE,GOTO MENU SETFLG DEC EOFFLG ;SET ENDFILE FLAG ; ; WHEN GOOD READ OR EOF GET HERE. ASK USER TO INSERT DESTINATION ; DISK AND ATTEMPT TO WRITE TO DESTINATION FILE. ; INSDES LDX #IDDH ;ARG: ADDRESS OF LINE TO BE PRINTED LDA #IDDL ;IN REGS A AND X JSR DSPLIN ;SAY TO SWAP DISKS JSR GETLIN ;WAIT TIL USER HITS BIT PER ;WAS BREAK KEY HIT? BPL DODEST ;NO, TRY WRITE JMP CLSSRC ;YES, CLOSE & GOTO MENU ; ; CHECK IF FIRST TIME SOURCE WAS READ. IF YES, THEN OPEN FOR OUTPUT ; ONLY. OTHERWISE, OPEN FOR OUTPUT APPEND. ; DODEST LDX #$20 ;USE IOCB #3 FOR DESTINATION LDY #9 ;ASSUME APPEND LDA FTRF ;IS FLAG CLEAR? BNE OPNDES ;NO,NOT FIRST TIME - OPEN APPEND LDY #8 ;YES, THEN OPEN OUT ONLY INC FTRF ;SET TO SHOW NOT FIRST TIME NEXT TIME ; OPNDES TYA ;GET OPEN TYPE CODE STA ICAX1,X ;SET AUX1 BYTE LDA #OPEN  ;OPEN COMMAND STA ICCOM,X ; ; THE FILENAME IS THE FIRST FILE IN THE PARAMETER LIST-PAR. ; LDA #PARL ;SET BUFFER ADDRESS TO FILE SPEC TO BE OPENED LDY #PARH BIT WCFLAG ;IF WILDCARD USE WILDCARD BUFFER INSTEAD OF PAR BVC SKIPWC ; LDA #.LOW.WCBUF2 LDY #.HIGH.WCBUF2 ; SKIPWC STA ICBAL,X TYA STA ICBAH,X JSR CIOCL ;CALL CIO, IF ERROR GOTO MENU ; ; CHECK IF SOURCE BUFFER LENGTH IS NOT EQUAL TO ZERO. IF NOT = ZERO ; THEN WRITE BUFFER TO THE DESTINATION FILE. ; LDY #$10 ;SOURCE IS AT IOCBB #2 LDX #$20 ;DEST IS AT IOCB #3 LDA #0 ;CHECK LENGTH LOW FOR ZERO CMP ICBLL,Y ;LOW=0 BNE DOWRIT ;NO THEN WRITE BUFFER CMP ICBLH,Y ;IS HI=0? BEQ CLSDES ;YES, DON'T WRITE EMPTY BUFFER ; DOWRIT LDA #PUTCHR ;PUT CHAR COMMAND CODE STA ICCOM,X ;IGNORE EOLS (9B) LDA BUFADR ;GET BBUFFER ADDRESS STA ICBAL,X LDA BUFADR+1 STA ICBAH,X LDA ICBLL,Y ;GET BUFFER LENGTH TO WRITE STA ICBLL,X ;FROM IOCB OF SOURCE FILE LDA  ICBLH,Y ;SET BY GET TO ACTUAL BYTE STA ICBLH,X ;COUNT READ INTO BUFFER JSR CIOCL ;DO WRITE - IF ERR GOTO MENU ; ; CLOSE DESTINATION FILE ; CLSDES LDA #CLOSE ;CLOSE COMMAND CODE STA ICCOM,X ;CALL CIO - IF ERROR GOTO JSR CIOCL ;MENU AFTER PRINT MSG ; ; TEST ENDFILE FLAG. IF IT IS SET THEN COMPLETED DUPLICATION. ; OTHERWISE, DO LOOP BODY AGAIN (READ THEN WRITE). ; LDA EOFFLG ;IS SOURCE AT ENDFILE? BNE CLSSRC ;YES, THEN DONE ; ; ASK USER TO INSERT SOURCE FOR NEXT READ & THEN REPEAT LOOP ; LDX #ISDH ;ARGS: ADDRESS OF LINE TO PRINT IN LDA #ISDL ;REGS A AND X JSR DSPLIN  ;SAY TO INSERT SOURCE JSR GETLIN ;WAIT TIL USER HITS BIT PER ;WAS BREAK KEY HIT? BMI CLSSRC ;YES, CLOSE & GOTO MENU JMP DODUP ;REPEAT LOOP ; ; ******************END OF LOOP ; ; CLOSE SOURCE AND RETURN TO MENU ; CLSSRC LDX #$10 ;SOURCE AT IOCB #2 LDA #CLOSE ;CLOSE COMMAND CODE STA ICCOM,X JSR CIO ;CALL CIO ; BIT WCFLAG ;TEST IF 'DUPLICATE WILDCARD' MODE BVC DUPFEX ;BRANCH IF NOT 'DUPLICATE WILDCARD' MODE LDX #ISDH ;INSERT SOURCE MESSAGE LDA #ISDL JSR DSPLIN ;NEEDED TO GET NEXT WILDCARD DIRECTORY ENTRY JSR GETLIN ;WAIT FOR CR JSR PERX ;IF BREAK-KEY ABORT - EXIT TO MENU JMP WCOPYL ;JUMP TO WILDCARD LOOP DUPFEX = * ; JMP MENUSL ;GO TO THE MENU .PAGE ; **** ASK IF OK TO USE PROGRAM AREA ROUTINE ****^ H ; ; ;ASK USER IF CAN USE PROGRAM AREA. IF SAY YES ('Y') THEN ;ASSIGN BUFFER ADDRESS AS ALL AVAILABLE MEMORY. OTHERWISE, USE ;DBUF (250 BYTES) AS THE BUFFER. ASSIGNS BUFFER LENGTH. ; ;NO PARAMETERS ;RETURNS: BUFADR-BUFFER ADDRESS ; : BUFLEN-BUFFER LENGTH ; USEPGM LDA WARMST ;CHECK IF PGM AREA ALREADY BEQ USEDB4 ;USED-YES, USE IT AGAIN LDA #OKL ;ARGS: IN A AND X ADDR LDX #OKH ;OF LINE TO DISPLAY JSR DSPLIN ;ASK TO USE PGM AREA LDA #CMSIL ;SAY A Y RESPONSE WILL LDX #CMSIH ;INVALIDATE MEM.SAV JSR DSPLIN ;PRINT CAUTION JSR CHRGET ;GET 1ST CHAR OF CMP #'Y ;USERS RESPONSE BNE USEBUF ;NO THEN USE DBUFF ; ;USE ALL MEMORY AVAILABLE-PROGRAM AREA ;MEMLO,MEMTOP,BUFADR,BUFLEN ARE IN LSB,MSB FORM ; USEDB4 LDA #0 ;CLEAR WARMSTART FLAG STA WARMST ;TO SHOW PGM AREA USED STA MEMFLG ;SHOW NO USER AREA GOOD-MEM.SAV ALSO LDA #NMDUPL ;USE ALL AVAILABLE STA BUFADR ;MEMORY-FROM END OF DUP TO MEMTOP LDA #NMDUPH ;BUFADR HAS BUFFER STA BUFADR+1 ;ADDRESS LDA MEMTOP ;GET LENGTH OF SEC ;PGM AREA SBC #NMDUPL STA BUFLEN ;LSB,MSB ORDER LDA MEMTOP+1 SBC #NMDUPH STA BUFLEN+1 ; ; FIND THE GREATEST MULTIPLE OF 125 LESS THAN THE PROGRAM AREA ; THEN SET BUFFER LENGTH TO IT. THIS PREVENTS FRAGMENTATION TO FILE ; WHEN APPEND IS USED IN DUPFIL. ; LDA #0 ;INITIALIZE MULTIPLE OF 125 (MLT125) TO ZERO STA MLT125 STA MLT125+1 ; ;  DO UNTIL (MLT125 > BUFLEN) ; FINDGM LDA #125 ;INC THE MULTIPLE OF 125 BY 125 CLC ;TO GET THE NEXT HIGHER MULTIPLE ADC MLT125 STA MLT125 LDA #0 ADC MLT125+1 ;MLT125 IS IN LSB,MSB ORDER STA MLT125+1 ; ; TEST FOR MLT125 > BUFLEN - LOOP TEST ; LDA BUFLEN+1 ;IS MSB OF MLT125 > MSB OF BUFLEN? CMP MLT125+1 BCC GETMLT ;YES, THEN END LOOP BNE FINDGM  ;IF MLT LSB BUFLEN? BCS FINDGM ;NO, REPEAT LOOP ; ;ELSE END LOOP. ; END OF LOOP*********************** ; ; CHECK IF MULTIPLE = TO 125. IF IS, THEN LEAVE BUFLEN AS IS. IF ; ISN'T THEN SET BUFLEN TO THAT NULTIPLE OF 125 MINUS 125. ; GETMLT LDA MLT125+1 ;IS MSB NOT = ZERO? BNE REPLAC ;YES, VALUE IS > 125 LDA #125 ;IS LSB > 125? CMP MLT125 ; BCC REPLAC ;YES, REPLACE BUFLEN WITH MLT125 RTS ;ELSE LEAVE BUFLEN AS IS ; ; REPLAC LDA MLT125 ;SUBTRACT 125 FROM MLT125 TO GET SEC ;GREATEST MULTIPLE LESS THAN OR EQUAL SBC #125 ;TO THE PROGRAM AREA. STA BUFLEN ;USE IT AS THE BUFFER LENGTH. LDA MLT125+1 SBC #0 STA  BUFLEN+1 RTS ;RETURN ; ;USE BUFFER DBUF (250 BYTES) INSTEAD OF PROGRAM AREA ; USEBUF LDA #DBUFL ;USE DBUF AS STA BUFADR ;BUFFER ADDRESS LDA #DBUFH ;IN LSB,MSB ORDER STA BUFADR+1 ; LDA #EDBLL ;STORE DATA STA BUFLEN ;BUFFER LENGTH LDA #EDBLH ;=TO 256(100HEX) STA BUFLEN+1 ;IN LSB,MSB ORDER RTS ;RETURN .PAGE ; **** CHECK FILENAME  FOR WILDCARD CHARACTERS ****^ H ; ; ; CHECKS THE STRING AT PAR,X FOR WILD CARD CHARACTERS (* OR ?). IF ; THEY ARE FOUND THE ROUTINE SETS THE EQUAL FLAG. IF A IS FOUND ; RETURNS TO THE CALLING ROUTINE WITH THE EQUAL FLAG RESET. ; LOOKWC LDA PAR,X INX CMP #'* BEQ LOOKW2 CMP #'? BEQ LOOKW2 CMP #CR BEQ LOOKW1 CMP #', ;TERMINATE WITH CR OR COMMA BNE LOOKWC ; LOOKW1 INX LOOKW2 RTS .PAGE ; **** TEST FILE SPEC FOR DOS.SYS ****^ H ; ; ; SUBROUTINE - TSTDOS ; ; CHECKS A FILE SPEC IN THE STORAGE LOC FOR DOS.SYS. USED TO ; PREVENT COPYING TO A FILE NAMED DOS.SYS. IF DOS.SYS IS OPENED ;  OUTPUT FMS WILL WRITE A COPY OF DOS OUT TO THE FILE. ; ; ENTRY - REG X HAS INDEX INTO PAR TO FIRST CHAR OF FILE SPEC ; ASSUMES COMPLETE FILE SPEC. ; EXIT - WILL NOT RETURN IF FILE NAME = DOS.SYS, BUT GOES TO MENU. ; ;  FIND END OF DEVICE ID - COLON ; TSTDOS INX ;NEVER IS FIRST CHAR LDA PAR,X ;GET 2ND CHAR CMP #': ;IS IT A COLON? BEQ GOTCOL ;YES, THEN NAME STARTS AT CHAR 3 INX ;ELSE NAME STARTS AT CHAR 4 GOTCOL INX ;POINT AT FIRST CHAR OF NAME ; ; COMPARE FILE NAME IN PAR WITH DOS.SYS ; LDY #0 ;INDEX INTO DOS.SYS FILE SPEC ; NXTCHAR LDA DS+3,Y ;GET NEXT DOS.SYS CHAR CMP PAR,X ;TEST IF FILE NAME IS SAME BNE NOTSAM ;NO, THEN RETURN INY ; INX ;ELSE TRY NEXT CHAR CPY #7 ;ARE THERE MORE CHARS TO TRY? BNE NXTCHAR ;YES, DO AGAIN ; ; FILE NAME EQUALS DOS.SYS - ERROR EXIT ; LDA #DCDSL ;PRINT MSG - DEST CAN'T BE DOS.SYS LDX #DCDSH JSR DSPLIN JMP MENUSL ;GOTO MENU ; ; NOT EQUAL TO DOS.SYS - RETURN TO CALLER ; NOTSAM RTS ; DCDS .BYTE 'DESTINATION CANT BE DOS.SYS',CR HILO DCDS .PAGE ; **** SAVE FILE ROUTINE ****^ H ; ; SAVFIL .WORD SFMG LDA #0 STA INITQ+1 STA RUNQ+1 JSR GETIC1 LDA OPT PHA LDX PTR ;PUT EOL ON FILENAME LDA #CR STA PAR-1,X JSR GETNO ;GET HEX PARAMETER STA LDST STX LDST+1 CPX #NDSH BCS  DSLMFG ;BRANCH IF NOT SAVING DUP AREA DEC WDR1+1 DSLMFG JSR GETNO ;END ADDRESS STA LDND STX LDND+1 SEC SBC LDST STA WDRL+1 TXA SBC LDST+1 BPL  ADDOK ;BRANCH IF ENDING ADDRESS GREATER THAN STARTING JMP MENUSL ;ELSE BACK TO MENU ADDOK STA WDRH+1 CPY #CR BEQ NRUNAD ;BRANCH IF NO MORE PARAMS JSR GETNO ;GET A RUN ADDRESS IF ANY STA INITAD STX INITAD+1 ORA INITAD+1 BEQ NINTAD ;BRANCH IF NO INIT ADDRESS GIVEN DEC INITQ+1 ;SET FLAG NINTAD CPY #CR BEQ NRUNAD ;BRANCH IF NO RUN ADDRESS GIVEN JSR GETNO ;GET RUN ADDRESS JSR PERX ;CHECK FOR ERRORS STA RUNAD STX RUNAD+1 ORA RUNAD+1 BEQ NRUNAD ;BRANCH IF NO RUN ADDRESS DEC RUNQ+1 ;SET FLAG NRUNAD LDA #0 STA OPT PLA ;OPTION CHAR FROM FILENAME CMP #'A ;IF APPEND BNE *+5 DEC OPT ;SET OT=$FF ; OPEN THE FILE LDX #$10 LDA #OPEN  STA ICCOM,X BIT OPT ;IF APPEND BMI *+6 LDA #8 BNE *+4 LDA #9 STA ICAX1,X JSR CIOCL ; WRITE SAVE FILE HEADER LDA #PUTCHR STA ICCOM,X  LDA #SAVHL STA ICBAL,X LDA #SAVHH STA ICBAH,X LDA #6 STA ICBLL,X LDA #0 STA ICBLH,X BIT OPT BPL WHEAD ;BRANCH IF NOT APPEND  LDA #4 STA ICBLL,X LDA #LDSTL STA ICBAL,X LDA #LDSTH STA ICBAH,X WHEAD JSR CIOCL ; WRITE DATA RECORD WDR LDX #$10 WDRL LDA #0 ;THIS IMMEDIATE VALUE MODIFIED  STA ICBLL,X WDRH LDA #0 ;THIS IMMEDIATE VALUE MODIFIED STA ICBLH,X INC ICBLL,X BNE *+5 INC ICBLH,X LDA LDST STA ICBAL,X LDA LDST+1 STA ICBAH,X WEX JMP WDR1 SFMG .BYTE 'SAVE-GIVE FILE,START,END' .BYTE $5B,',INIT,RUN',$5D,CR .PAGE ; **** MISC. SUBROUTINES ****^ H ; ; GETLIN LDA #CR LDX #79 STA LINE,X DEX  BPL *-4 LDA #0 STA PTR STA IPTR STA PER JSR CIOGET JSR SCROL RTS ; ; ; ; CIOGET - GET LINE OF INPUT FROM SCREEN EDITOR ; CIOGET LDA #GETREC STA ICCOM  ;SCREEN EDIT IOCB LDA #LBUFL STA ICBAL LDA #LBUFH STA ICBAH LDA #80 STA ICBLL LDA #0 STA ICBLH LDX #0 JSR CIO ;READ RECORD FROM SCREEN EDITOR CPY #$80 ;CHECK FOR BREAK ABORT STATUS BNE *+5 DEC PER ;PARAM ERROR FLAG IS SET IF SO RTS ; ; ; CHRGET - GET 1 CHAR FROM EDITOR IN A. ; CHRGET LDA #0 STA PER CHRG1 JSR CIOGET ;GET A LINE FROM E: LDA ICBLL ;SAVE CHAR COUNT STA RCNT JSR SCROL LDA PER BPL CHRG2 ;IF BREAK, CLOSE AND EXIT JSR CLOSX JMP MENUSL CHRG2 LDA RCNT ;EXPECT 1 OR 2 CHARACTERS CMP #3 BMI CHRG3 ;IF OK LDA #OLL LDX #OLH JSR DSPLIN JMP CHRG1 ;TRY AGIN CHRG3 LDA LINE ;GET 1ST CHAR  RTS .PAGE OL .BYTE 'PLEASE TYPE 1 LETTER',CR HILO OL ; ; PERX - EXIT IF PARAMETER ERRORS ; PERX BIT PER BMI PERX1 RTS PERX1 PLA PLA JMP MENUSL ; ; GETIC1 - READ LINE, GET FILENAME, POINT TO IT IN IOCB1 ; GETIC1 JSR GETLINE GETIC2 LDX #$10 JSR PIOCB JMP GETFIL ; ; GETNAME LDA #8 ;ENTRY TO GETFIL USED BY RENAME STA CTR ;WHICH DOES NOT HAVE A DEVICE ID LDY  PTR ;FOR THE SECOND FILE SPEC LDX IPTR JMP CFTE ; ; SUBROUTINE - GETFIL^ H ; REMOVES ONE FILE SPECIFICATION FROM THE INPUT LINE. WILL SET UP ; THE SPEC FOR DEFAULTS FOR INCOMPLETE DRIVE ID. DEFAULT DRIVE # IS ; 1. ; ; ;GET FILESPEC FROM INPUT LINE GETFIL LDY PTR LDX IPTR LDA #11 STA CTR ;AVOID GETTING JUNK ON VERY SHORT PARAMS LDA LINE,X CMP #', BEQ ADDC CMP  #CR BEQ ADDC LDA LINE+1,X CMP #', BEQ GT1 CMP #CR BEQ GT1 LDA #': ;LOOK FOR : IN FILESPEC CMP LINE+2,X ;SEE IF HAVE COMPLETE FILESPEC ALREADY  BEQ CFTE CMP LINE+1,X BNE GT1 DEC CTR LDA LINE,X CMP #'A BPL CFTE ;HAVE X:FILE, COMPLETE FILESPEC ;IF FALLS THRU, IS UNIT:FILE; ADD D GT2 LDA #'D STA PAR,Y INY BPL CFTE GT1 DEC CTR DEC CTR CMP LINE,X ;AN UNLIKELY CASE (:FILE) BEQ GT2 ;TREAT :FILE AS U:FILE DEC CTR ADDC LDA #'D STA PAR,Y  INY LDA #': STA PAR,Y INY CFTE LDA #0 STA OPT CFTE1 LDA LINE,X STA PAR,Y INX INY CMP #CR ;LOOK FOR TERMINATOR BEQ EOC CMP  #', BEQ EOC CMP #'/ BEQ POPT CMP #'. ;LOOK FOR START OF .EXT BNE CFTE2 LDA #4 ;FOUND, 4 MORE CHARS MAX STA CTR CFTE2 DEC CTR BPL CFTE1 ;GETS HERE IF TOO MANY CHARS IN FILENAME LDA #NTLL LDX #NTLH JSR DSPLIN ;NAME TOO LONG DEC PER ;SET PARAMETER ERROR FLAG STE LDA LINE,X ;SKIP TO END INX CMP #',  BEQ EOC CMP #CR BNE STE EOC STX IPTR STY PTR RTS POPT LDA LINE,X STA OPT INX LDA LINE,X STA PAR-1,Y ;CHANGE STORED TERMINATOR TO , OR CR I HOPE INX BPL EOC NTL .BYTE 'NAME TOO LONG',CR HILO NTL ; ; DSPMSG - DISPLAY N BYTES ; BUFFER POINTER AND LENGTH ARE ALREADY IN IOCB0 ; DSPMSG LDA #PUTCHR STA ICCOM LDX #0 ; CIO1 JSR CIO ;CALL CIO AND GO TO MENUSL CPY #$80 ;IF BREAK KEY ABORT BNE *+5 JMP MENUSL RTS ; ; DSPLIN - DISPLAY ONE LINE OF TEXT ; A=LO,X=HI ADDRESS DSPLIN JSR PRNTMSG ;USE RESIDENT DUP SUBROUTINE JMP SCROL ;SCROLL SCREEN BELOW MENU & RETURN ; ; ; SCROL - DO SCROLLING OF AREA BELOW MENU ; SCROL LDA #0 TAX STA ICBLH,X LDA #10 STA ICBLL,X LDA #ZAPH  STA ICBAH,X LDA #ZAPL STA ICBAL,X JMP DSPMSG .PAGE ZAP .BYTE CUP,CUP,CUP,CUP,CUP .BYTE DLL,CDN,CDN,CDN,CDN HILO ZAP ; ; PIOCB - POINT IOCB AT PAR(PTR) ; PIOCB LDA #PARL CLC ADC PTR STA ICBAL,X LDA #PARH ADC #0 STA ICBAH,X RTS ; ; CIOCL - CALL CIO AND PROCESS ANY ERRORS ; CIOCL JSR CIO ;CALL CIO TYA BMI *+3  RTS ;OK, RETURN CIOER1 TYA ;ERROR STATUS CIOER SEC SBC #100 ;ERROR NUMS ALWAYS ARE 1XX DEC LDX #'0-1 ;CONVERT TENS CTNS INX SEC SBC #10 BPL CTNS ;THE EASY (SLOW) WAY CLC ADC #10+'0 ;CONVERT STA EUN STX ETN LDX #CIEH LDA #CIEL CIEX JSR DSPLIN JSR CLOSX ;CLOSE IOCBS 10,20 JMP MENUSL CIE .BYTE 'ERROR- 1' ETN .BYTE 0 EUN .BYTE 0 .BYTE CR HILO CIE ; ; ; GETNO - GET HEX NUMERIC PARAMETER FROM LINE(IPTR). ; RETURN A=LO, X=HI. PER SET MINUS IF ERROR. ; INC IPTR PAST PARAM. ; GETNO LDA #4 ;MAX NO DIGITS STA CTR LDA #0 STA T1 STA T1+1 ;INIT TEMP TO BUILD NUMBER IN GHB LDX IPTR LDA LINE,X ;GET CHAR INC IPTR CMP #CR  ;SEE IF TRMINATOR BEQ GND CMP #', BEQ GND JSR HEXCON ;CONVERT ASCII TO NIBBLE BMI ERRX ;IF ERROR LDY #3 ;SHIFT T1,T1+1 BY 4 SHT1 CLC ROL T1+1  ROL T1 DEY BPL SHT1 ORA T1+1 ;OR IN NEW NIBBLE STA T1+1 DEC CTR ;COUNT DIGIT BPL GHB ;LOOP UNLESS TOO MANY DIGITS LDA #TMDL LDX #TMDH ERRX1 JSR DSPLIN DEC PER RTS GND TAY LDA T1+1 LDX T1 RTS ERRX LDA #IHPL ;INVALID HEX PARAM LDX #IHPH BNE ERRX1 TMD .BYTE 'TOO MANY DIGITS',CR  HILO TMD IHP .BYTE 'INVALID HEXADECIMAL PARAMETER',CR HILO IHP ; ; ; HEXCON - CONVERT ASCII CHAR IN A TO HEX NIBBLE IN A. RETURN ; MINUS CONDITION, A=FF IF ERROR. ; HEXCON SEC SBC #'0 BMI ERRX2 ;ASCII BELOW '0' CMP #10 BMI OKX ;0-9 CONVERTED SO EXIT SEC SBC #'A-'0-10 CMP #10 ;CONVERTED VALUE MUST BE 10 OR MORE BMI ERRX2 ;BETWEEN '9' AND 'A' CMP #$10 BMI OKX ;A-F CONVERTED ERRX2 LDA #$FF OKX CMP #0 ;SET STATUS BY VALUE IN A RTS ; ; GETDN - GET A DEVICE NUMBER FROM LINE(IPTR) ; RETURN IT IN A ; GETDN BIT PER ;SEE IF PARAM ERROR ALREADY BMI GDR ;IF SO DONT BOTHER LDX IPTR GETD LDA LINE,X INX CMP #'D ;IF DN BEQ GETD ;GO GET DIGIT SEC SBC #'0 ;CONVERT DIGIT  BEQ BDS ;CANT BE ZERO BMI BDS ;IF NOT DIGIT CMP #DRTST ;TEST FOR BEYOND DRIVE MAX BPL BDS ;TOO LARGE PHA GD1 LDA LINE,X INX CMP #', BEQ  GDX ;IF TERMINATOR CMP #CR BNE GD1 ;KEEP LOOKING GDX STX IPTR ;ADVANCE POINTER PLA GDR RTS BDS DEC PER LDA #NDSL ;NEED DEVICE SPEC MSG LDX #NDSH  JMP DSPLIN NDS .BYTE 'NEED D1 THRU D8',CR NMDUP .BYTE 0 LEN = NMDUP-EDN HILO LEN MLEN = NMDUP-NDOS HILO MLEN HILO NDS HILO NMDUP .END .TITLE 'FMS - 128/256 BYTE SECTOR' LIST X ; PROGRAMMER PAUL LAUGHTON ; 4.9D 05-FEBRUARY-81 ; SPECIAL VERSION FOR 815 2.0D ; ;********************************************************************* ; (C) 1978 SHEPARDSON MICROSYSTEMS, INC ;********************************************************************* ; ;********************************************************************* ; FILENAME: DOS2.FMSDUAL ON TANDEM ;************************************* ******************************** ; ; FMSORG = $700 FMSZPG = $43 IOCBORG = $340 LMASK = 03 ; LINK MASK DCBORG = $300 DHADR = $E453 EOL = $9B DEVTAB = $31A ZICB = $20 LMADR = $2E7 DU PINIT = $1540 ;INIT ADDRESS FOR DUP STAK = $102 ; STACK LOC FOR PUT BYTE OSBTM = $DF ; HI BYTE OF ADDRESS LESS THAN OS SPACE, IN PUT DSKTIM = $246 ; ADDR OF OS WORST CASE DISK TIME OUT TIMOUT = 15 ; TIME OUT VALUE OF 15 SECONDS .PAGE 'IOCB' *= IOCBORG ; ; IOCB - I/O CONTROL BLOCK ; THERE ARE 8 I/O CONTROL BLOCKS ; 1 IOCB IS REQUIRED FOR EACH ;  CURRENTLY OPEN DEVICE OF FILE. ; IOCB ICHID *=*+1 ; DEVICE HANDLER ID ICDNO *=*+1 ; DEVICE NUMBER ICCOM *=*+1 ; I/O COMMAND ICSTA *=*+1 ; I/O STATUS ICBAL *=*+1 ICBA H *=*+1 ; BUFFER ADR (H,L) ICPUT *=*+2 ; PUT CHAR DH ADR ICBLL *=*+1 ICBLH *=*+1 ; BUFFER LENGTH (H,L) ICAUX1 *=*+1 ; AUXILLIARY 1 ICAUX2 *=*+1 ; AUXILLIARY 2 ICAUX3 *=*+1 ; AUXILLARY 3 ICAUX4 *=*+1 ; AUXILLARY 4 ICAUX5 *=*+1 ICAUX6 *=*+1 ICLEN = *-IOCB ; *=*+ICLEN*7 ; SPACE FOR 7 MORE IOCBS ; ; ICCOM VALUE EQUATES ; ICOIN  = $01 ; OPEN INPUT ICOOUT = $02 ; OPEN OUTPUT ICOIO = $03 ; OPEN UN/OUT ICGBR = $04 ; GET BINARY RECORD ICGTR = $05 ; GET TEXT RECORDS ICGBC = $06  ; GET BINARY CHAR ICGTC = $07 ; GET TEXT CHAR ICPBR = $08 ; PUT BINARY RECORD ICPTR = $09 ; PUT TEXT RECORD ICPBC = $0A ; PUT BINARY CHAR ICPTC = $0B ; PUT TEXT CHAR ICCLOSE = $0C ; CLOSE FILE ICSTAT = $0D ;GET STATUS ICDDC = $0E ; DEVICE DEPENDENT ICMAX = $0E ; MAX VALUE ICFREE = $FF ; IOCB FREE INDICATOR ; ;  ICSTA VALUE EQUATES ; ICSOK = $01 ; STATUS GOOD, NO ERRORS ICSTR = $02 ; TRUNCATED RECORD ICSEOF = $03 ; END OF FILE ICSBRK = $80 ; BREAK KEY ABORT ICSDNR = $81  ; DEVICE NOT READY ICSNED = $82 ; NON-EXISTENT DEVICE ICSDER = $83 ; DATA ERROR ICSIVC = $84 ; INVALID COMMAND ICSNOP = $85 ; DEVICE/FILE NOT OPEN ICSIVN = $86  ; INVALID IOCB NUMBER ICSWPE = $87 ; WRITE PROTECTION ; ; ZERO PAGE IOCB LABELS ; ICDNOZ = ICDNO-IOCB+ZICB ; DRIVE # ICBLLZ = ICBLL-IOCB+ZICB ; BUF LENGTH ICBLHZ = ICBLH-IOCB+ZICB ; ICBALZ =  ICBAL-IOCB+ZICB ; BUF ADR ICBAHZ = ICBAH-IOCB+ZICB ICCOMZ = ICCOM-IOCB+ZICB ICPUTZ = ICPUT-IOCB+ZICB ; PUT ROUTINE ADDRESS .PAGE 'DCB' *= DCBORG ; ; DCB - DATA CONTROL BLOCK ;  THE DCB IS A IOCB LIKE CONTROL BLOCK USED ; TO INTERFACE THE DISK FILE MANAGEMENT SYSTEM ; TO THE DISK HANDLER ; DCB DCBSBI *=*+1 ; *SERIAL BUS ID DCBDRV *=*+1 ; -DISK DRIVE NUMBER DCBCMD *=*+1 ; -COMMAND DCBSTA *=*+1 ; * U/O STATUS DCBBUF *=*+2 ; -I/O BUFFER ADR (H,L) DCBTO *=*+2 ; *TIME OUT COUNT (H,L) (1/60 SEC) DCBCNT *=*+2  ; *U/O BYTE COUNT (H,L) DCBSEC *=*+2 ; I/O SECTOR NUMBER (H,L) ; ; DCBCMD VALUE EQUATES ; DCBCRS = $52 ; READ SECTOR DCBCWS = $57 ; WRITE SECTOR DCBCST = $53 ; STATUS REQUEST DCBCFD = $21 ; FORMAT DISKETTE ; ; DCBSTA VALUE EQUATES ; DCBSOK = $01 ; STATUS NORMAL DCBDNR = $81 ; DEVICE NOT READY DCBCNR = $82 ; CONTROLLER NOT READY DCBDER = $83 ; DATA ERROR DCBIVC = $84 ; INVALID COMMAND DCBWPR = $87 ; WRITE PROTECT .PAGE 'ZERO.PAGE' *= FMSZPG ZBUFP *=*+2 ;BUFFER PTR ZDRVA *=*+2 ;ZERO .PAGE DRIVE PTR ZSBA *=*+2 ; ZERO .PAGE SECTOR BUFF PTR ERRNO *=*+1 ;ERROR NUMBER .PAGE 'BOOT RECORD' *= FMSORG ; ; THEFOLLOWING BYTES ARE STORED ON DISK ; SECTOR 0 THEY COMPRISE THE BOOT LOADER ; RECORD. ; BFLG .BYTE 0 ;BOOT FLAG (UNUSED,=0) BRCNT .BYTE 3 ; NO CONSECTUTIVE BOOT SECTORS TO READ BLDADR .WORD FMSORG ;BOOT LOAD ADR BINTADR .WORD DUPINIT ;INITILZATION ADR BCONT JMP XBCONT ;BOOT READ CONTINUE ENTRY POINT ; ; THE FOLLOWING BYTES ARE SET BY THE CONSOLE PROCESSOR. ; THEY ARE ACTED UPON DURING FMS INIT ONLY. ; THEY ARE PART OF THE BOOT RECORD, THUS DEFINING ; THE DEFAULT INITILIZATION PARMS. ; SABYTE .BYTE 3 ;MAX NUMBER CONCURRENT OPEN FILE DRVBYT .BYTE 01 ; DRIVE BITS SAFBSW .BYTE 0 ;STORAGE ALLOCATION DIRECTION SWITCH SASA .WORD ENDFMS ;STORAGE ALLOCATION START ADR ; ; THE FOLLOWING CODE READS THE FMS AND CONSOLE ; PROCESSOR (DOS) FROM THE DOS.SYS FILE ; DFSFLG .BYTE 0 ; DOS FLAG ; 00 - NO DOS FILE ; 01 - 128 BYTE SECTOR DI SK ; 02 - 256 BYTE SECTOR DISK DFLINK .BYTE 0,0 ; DOS FILE START SECTOR NUMBER BLDISP .BYTE 125 ; DISPL TO SECTOR LINK DFLADR .WORD DFMSDH ; ADR START OF DOS.SYS FILE ; XBCONT ! LDY DFSFLG ; GET DOS FLAG BEQ BFAIL ; BR IF NO DOS.SYS FILE ; LDA DFLADR ; MOVE LOAD START ADR STA ZBUFP ; TO ZERO PAGE PTR STA DCBBUF ; AND TO DCB LDA" DFLADR+1 STA ZBUFP+1 STA DCBBUF+1 ; ; LDA DFLINK+1 ;GET FIRST SECTOR NUMBER LDY DFLINK XBC1 CLC ;SET READ LDX DFSFLG ; LOAD DISK TYPE CODE J#SR BSIO ;GO READ BOOT SECTOR BMI BFAIL ; LDY BLDISP ;POINT TO LINK LDA (ZBUFP),Y ; GET LINK HI AND #LMASK ;MASK TO LINK BITS PHA ;SAV$E INY ORA (ZBUFP),Y BEQ BGOOD LDA (ZBUFP),Y ; GET LINK LOW TAY ; TO Y JSR INCBA ;GO INCREMENT BUF ADR ; PLA ;RESTOR LINK HI % JMP XBC1 ;GO READ NEXT SECTOR ; BFAIL LDA #$C0 ;SET FOR CARRY SET BNE XBRTN ;ANY P,Y = $80 ; BGOOD PLA ; SET FOR CARRY CLEAR ; ;AND A,Y = 0 XBRTN ASL A & TAY RTS ;DONE BOOT READ ; INCBA CLC LDA ZBUFP ; INC BUFFER POINTER ADC BLDISP ;BY DATA LENGTH (125) STA DCBBUF STA ZBUFP LDA ZBUFP+1 ' ADC #0 STA DCBBUF+1 STA ZBUFP+1 RTS ; .PAGE 'SECTOR I/O' ; ; BSIO - DO SECTOR I/O ; BSIO = * ; STA DCBSEC+1 ; SET SECTOR (HI) STY DCBSEC ( ; SET SECTOR (LOW) ; BSIOR LDA #DCBCRS ; ASSUME READ SECTOR LDY #$40 ; AND GET DATA BCC DSIO1 ; BR IF READ ; LDA #DCBCWS ; ELSE LOAD WRITE SEC)TOR LDY #$80 ; AND PUT DATA ; DSIO1 STA DCBCMD ; SET COMMAND STY DCBSTA ; AND SIO CMD ; LDA #$31 ; DISK SERIAL BUS ID LDY #TIMOUT* ; TIME OUT DEFAULT LOADED ; DSIO2 STA DCBSBI ; SET ID STY DCBTO ; SET TIME OUT ; LDA #3 ;SET RETRY COUNT STA RETRY ; LDA + #0 ; ASSUME 128 BYTE LDY #$80 ; SECTOR DISK DEX ; IF X=1 IS 128 BYTE BEQ DSIO3 ; SO BR ; LDA #1 ; ELS,E IS 256 LDY #0 ; DSIO3 STA DCBCNT+1 ; SET I/O BYTE COUNT STY DCBCNT ; DSIO4 JSR $E459 ; CALL SERIAL I/O BPL DSIO5 ; IF GOOD I/O THEN RETURN ; - DEC RETRY ; TEST IF ANOTHER RETRY AVAILABLE BMI DSIO5 ; NO, THEN RETURN WITH ERROR ; LDX #$40 ; DO RETRY - RESET TYPE ACTION LDA #DCBCRS ; .ASSUME READ - CHK IF IS CMP DCBCMD ; IS COMMAND GET SECTOR? BEQ STRTYP ; YES, THEN STORE GETSECTOR IN DCB LDA #DCBCFD ; TEST IF FORMAT COMMAND CMP DCBCMD / ; IT ALSO RECEIVES DATA BEQ STRTYP ; YES, THEN SET AS GET DATA LDX #$80 ; ELSE STORE PUTSECTOR STRTYP STX DCBSTA ; JMP DSIO4 ; RETRY THE I/O ;0 DSIO5 LDX CURFCB ; RELOAD CURRENT FCB LDA DCBSTA ; AND I/O STATUS, SET FLAGS RTS ; .PAGE 'FILE MANAGER ENTRY POINT' ; ; DFMSDH - DISK FILE MANAGEMENT DISK HANDLER ENTRY POINT ; 1DFMSDH .WORD DFMOPN-1 ; OPEN FILE .WORD DFMCLS-1 ; CLOSE FILE .WORD DFMGET-1 ; GET BYTE .WORD DFMPUT-1 ; PUT BYTE .WORD DFMSTA-1 ; STATUS .WORD DFMDDC-1 ; DE2VICE DEPENDENT CMND .PAGE 'INITILIZATION' ; ; INITILIZATION CODE ; *= $7E0 ; GIVE ROOM FOR BOOT EXPANSION!!!!! DINIT = * ; ; SET UP DRIVE INFO ; DRVTBL - 8 BYTES - ONE FOR EACH POSSIBLE 3DRIVES ; 0 = NO DRIVE ; 1 = 128 BYTE SECTOR DRIVE ; 2 = 256 BYTE SECTOR DRIVE ; DBUFA(L,H) - 8 TWO BYTE ENTRIES ; THE DRIVE (VTOC) BUFFER ADR FOR A DRIVE ; LDA SAS4A ; MOVE START OF ALLOCATION STA ZBUFP ; AREA TO ZBUFP LDA SASA+1 STA ZBUFP+1 ; LDA DRVBYT ; TEMP 1 IS DRIVE STA TEMP1 ; EXIST BITS FROM BOOT ; L5DX #7 ; TEMP2 IS ; DIA STX TEMP2 ; DRIVE NIMBER MINUS ONE ASL TEMP1 ; SHIFT DRIVE BIT TO CARRY BCS DIHAVE ; BR IF DRIVE EXISTS ; LDA #0 ; DRIVE DOES N6OT EXITS STA DRVTBL,X ; SET NO DRIVE STA DBUFAL,X ; AND NO BUFFER STA DBUFAH,X BEQ DIDDEC ; GO DEC DRIVE NO. ; DIHAVE LDY #DVDWRQ ; SET WRITE REQD OFF LDA7 #0 STA (ZBUFP),Y ; IN THE DRIVE BUFFER ; INX STX DCBDRV ; PUT DRIVE NO. INTO DCB LDA #DCBCST ; GET DRIVE STATUS STA DCBCMD JSR DHADR ; VIA OP SYS ;8 LDY #2 ; ASSUME 256 BYTE DRIVE LDA $2EA ; GET STATUS BYTE AND #$20 ; AND TEST 256 BNE DI256 ; BR IF 256 DEY ; DI256 TYA LDX TEMP2 9 ; SET DRIVE TYPE INTO STA DRVTBL,X ; TABLE AT DRIVE DISPL LDA ZBUFP ; MOVE CURRENT ALOC STA DBUFAL,X ; ADR TO DBUFA LDA ZBUFP+1 ; AND INC ALOC STA DBUFAH,X : ; BY 128 BYTES JSR DINCBP ; VIA DINCBP ; DEY ; IF DRIVE WAS A BEQ DIDDEC ; 128 BYTES THEN DONE ; JSR DINCBP ; ELSE INC PTR BY 128 ; DIDDEC DEX ; ; DEC DRIVE BPL DIA ; BR IF MORE TO TEST ; ; SET UP SECTOR ALLOCATION TABLE ; THE SECTOR ALLOCATION TABLE (SECTBL) HAS 16 ONE BYTE ; ENTRIES, ONE FOR EACH POSSIBLE 128 BYTE BUFFER SABYTE ;< IN THE BOOT RECORD DETERMINES THE NUMBER OF ENTRIES TO ; ALLOCATE. NON-ALLOCATED BYTES ARE MINUS. ; ; SABUF(L,H) CONTAIN THE ADR OF THE SECTOR BUFFER ; LDY SABYTE ; GET AND SAVE COUNT LDX = #0 ; SET CURRENT BUFFER NO. ; DINXTS LDA #0 ; ASSUME ALLOCATE DEY ; DEC COUNT OF ALLOCATED BPL DISETS ; IF PLUS STILL ALLOCATE TYA ; ELSE DE->ALLOCATE ; DISETS STA SECTBL,X ; SET ALLOCATE BYTE TYA ; IF NO ALLOCATED BMI DISNI ; THEN DON'T ALLOCATE BUFF ; LDA ZBUFP ; MOVE BUFFER ADDR STA SABUFL,X ? ; TO SECTOR BUF PTR LDA ZBUFP+1 STA SABUFH,X JSR DINCBP ; INC SECTOR ADDR ; DISNI INX ; INC BUFFER NO CPX #16 ; IF NOT ALL 16 BNE DINXTS @; DO AGAIN ; ; SET LOW MEM ; LDA ZBUFP ; MOVE FINAL ADDR STA LMADR ; TO LOMEM PTR LDA ZBUFP+1 STA LMADR+1 ; JMP CLRFCB ; CONTINUE INIT ; ; DINCBP - INCA ZBUFP BY 128 ; DINCBP CLC LDA ZBUFP ADC #128 STA ZBUFP LDA ZBUFP+1 ADC #0 STA ZBUFP+1 RTS ; ; CLEAR FCBS TO ZERO ; CLRFCB = * LDY #$7F B; 128 OF FCB LDA #0 CFCBX STA FCB,Y ; TO BE CLEARED DEY BNE CFCBX ; .PAGE ; LDY #0 ADI1 LDA DEVTAB,Y ;FIND AN BEQ ADI2 ; UNUSED CMP #'D C ; OR DISK BEQ ADI2 ; EMPTY INY INY INY CPY #30 BNE ADI1 BRK ; ELSE BREAK ; ADI2 LDA #'D ; SET DISK STA DEVTAB,Y D LDA #.LOW.DFMSDH ; SET FMS ADR STA DEVTAB+1,Y ; LDA #.HIGH.DFMSDH STA DEVTAB+2,Y ; RTS ; DONE INIT .PAGE 'OPEN' ; ; DFMOPN - FILE OPEN EXECUTION EENTRY POINT ; DFMOPN JSR SETUP ; DO FCB SET UP JSR FNDCODE ; GO DECODE FILE NAME LDA ICAUX1,X ; GET AUX1 (OPEN TYPE CODES) STA FCBOTC,X ; PUT INTO FCB AND #OPDIR F ; IS THIS LIST DIRECTORY BEQ OPN1 ; BR IF NOT JMP LISTDIR ; GO TO DIR LIST CODE ; OPN1 JSR SFDIR ; GO SEARCH FILE DIRECTORY PHP G 784 ; 785 LDA FCBOTC,X ; GET OPEN TYPE CODE 786 CMP #OPIN ; INPUT 7H87 BEQ DFOIN 788 CMP #OPOUT ; OUTPUT 78 BEQ DFOOUT 790 CMP I #OPIN+OPOUT ; UPDATE 7 ? BEQ DFOUPD 792 CMP #OPOUT+OPAPND ; APPEND 793 BEQ DFOAPN J 794 JMP ERDVDC ; ERROR ? ; 796 ; DFOIN - OPEN FOR INPUT K 797 ; 798 DFOIN = * 7 99 PLP ; GET SEARCH FLAG L 800 BCS OPNER1 ; ERROR IF NOT FOUND 801 BCC DFOUI 802 ; 803M ; DFOUPD - OPEN FOR UPDATE 804 ; 05 DFOUPD = * 806 PLP N ; GET SEARCH FLAG 807 BCS OPNER1 ; BR NOT FOUND 808 JSR TSTLOCK ; TEST LOCK 80 ; O 810 DFOUI = * 811 JSR DFRDSU ; SET UP FOR READ 812 JMP GREAT ; DONE P 81 ; 814 OPNER1 JMP ERFNF ; FILE NOT FOUND 815 .PAGE ; Q 1 ; DFOAPN - OPEN APPEND 818 ; 81 DFOAPN = * R 820 PLP ; GET READ STATUS 821 BCS OPNER1 ; BR NOT FOUND 822 LDY CDIRD ; IF OLD LDA FILDIR+DFDFL1,Y ; FILE TYPE S AND #DFDNLD ; THEN BEQ APOER ; ERROR JSR TSTLOCK ; TEST LOCKED 823 JSR OPVTOC ; READ VTOC JSR GETSECTOR ; GET A SECTOR T 825 STA FCBSSN+1,X ; MOVE START SECTOR NUMBER 826 LDA FCBLSN,X ; TO START SECTOR NUMBER 827 STA FCBSSN,X ; U 828 JMP DHFOX2 ; CONTINUE AS OPEN 82 APOER JMP ERAPO ; 830 ; DFOOUT - OPEN FOR OUTPUT V 831 ; 832 DFOOUT = * 833 PLP ; GET SEARCH FLAG 834 W BCS DFOX1 835 ; JSR XDEL0 ; DELETE THE FILE OR FILES 837 LDY CDIRD 838 JMP XOPN1A 839 ; 840 DFOX1 = * 841 LDA DHOLES ;Y WAS THERE A HOLE 842 BMI OPNER2 ; BR IF NO HOLE 843 STA CDIRS ; SAVE HOLE SECTOR AS CURRENT DIR SECT 844 JSR RDDIR ; GO READ CURRENTZ DIR SECTOR 845 LDA DHOLED ; MOVE HOLE DISPL TO 846 STA CDIRD ; CUR DIR DISPL 8 LDA DHFNUM ; MOVE HOLE FN [ 848 STA SFNUM ; TO CURRENT 849 JSR OPVTOC LDY CDIRD LDX #10 LDA #$20 852 OPN1B STA FI\LDIR+DFDPFN,Y ;BLANK FILL FILE ENTRY FOR FILENAME INY DEX 854 BPL OPN1B 855 LDX CURFCB ; ] 856 OPN1A = * JSR GETSECTOR ; GET A SECTOR LDY CDIRD ; GET DIR DISPL STA FILDIR+DFDSSN+1,Y ; PUT SECTOR INTO DIR REC ^ 860 LDA FCBLSN,X 861 STA FILDIR+DFDSSN,Y 862 ; 86 L_DA #DFDINU+DFDOUT+DFDNLD ; SET DIR ENTRY IN USE STA FILDIR+DFDFL1,Y 865 LDA #0 ; SET NOT LOCKED 866 STA FILDIR+DFDCNT+1,Y ; SET CO`UNT = 0 867 STA FILDIR+DFDCNT,Y ; SET COUNT = 0 868 ; 869 LDX #0 a 870 OPN2 LDA FNAME,X ; MOVE FILE NAME 871 CMP #'? ; IF WILD CARD 872 BEQ OPN2A ; CHANGE TO BLANK STA FILDIR+DbFDPFN,Y ; TO DIRECTORY 874 OPN2A = * INY 876 INX 877 CPX #11 c 878 BCC OPN2 879 ; 880 LDX CURFCB ; RESTdORE X REG 881 JSR WRTDIR ; GO WRITE DIRECTORY 882 DHFOX2 = * 883 JSR SETFCB e 884 JSR WRTN6 ; FIX UP AS IF WRITE 885 OPN3 LDA #FCBFAS ; SET NEW FILE 886 STA FCBFLG,X f 887 JSR TSTDOS ; IF NOT DOS BNE DHFOX3 ; BR JMP WRTDOS ; ELSE DO IT DHFOX3 = * JMP GREAT 888 ; g 889 OPNER2 JSR ERDFULL ; DIRECTORY FULL 8 0 ; 8 1 ; h 892 SETFCB = * LDA #0 ; CLEAR STA FCBFLG,X ; FLAG 895 OPNF1 LDA SFNUM ; MOVE FILE # TO FCB i896 ASL A ; LEFT JUSTIFED FN 89 ASL A 89 STA FCBFNO,X 899 jLDA #0 900 STA FCBDLN,X ; DATA LENGTH 901 STA FCBCNT,X ; SET CNT = 0 902 STA FCBCNT+1k,X 903 RTS 904 DFRDSU JSR SETFCB ; SET UP FCB 905 LDY CDIRD ; MOVE SlTART SECTOR TO LINK 906 LDA DFDFL1+FILDIR,Y ; SET NEW AND #DFDNLD ; SECTOR STA FCBSLT,X ; FLAG LDA FILDIR+DFDSSN,Y STA FCBLSN,X m 908 LDA FILDIR+DFDSSN+1,Y 909 STA FCBLSN+1,X 910 JSR RDNS0 ; READ FIRST SECTOR n 911 RTS ; DONE 12 .PAGE 'PUT BYTE' ; ; DFMPUT - PUT A FILE BYTE ; DFMPUT STA SVDBYT ; SAVE DATA BYTE LDA ICDNO,X o STA ICDNO-IOCB+ZICB JSR SETUP ; GO SET UP LDY ENTSTK ; CHK TO SEE IF ENTRY WAS NOT FROM CIO LDA STAK,Y ; IF HI BYTE RETURN IS NOT IN OS ADDRESS CMP #OSBTM ; SPACEp, THEN A NON-CIO ENTRY BCS FRMCIO ; BRANCH IF FROM CIO LDA #0 ; ELSE PREVENT DOING BURST I/O STA ICCOMZ FRMCIO LDA FCBOTC,X ; IF NOT OPEN AND #OPOUT ; OUTPUT q BEQ PUTER ; ERROR LDY FCBDLN,X ; GET DATA LENGTH TYA CMP FCBMLN,X ; IF SECTOR NOT F1LL BCC PUT1 ; THEN BR JSR WRTNXS ; ELSE WRITE FULL SECTOR r BCS PEOF ; BR IF EOF JSR WTBUR ; TEST BURST LDY #0 ; BCS PUT1 ; BR IF NO BURST LDA (ICBALZ),Y ; PUT NEXT BYTE STA SVDBYT ; AFsTER BURST AREA ; PUT1 INC FCBDLN,X ; INC DATA LENGTH LDA SVDBYT ; GET DATA BYTE STA (ZSBA),Y ; AND PUT IN SECTOR BUFFER ; LDA #FCBFSM ; INDICATE SECTOR MODIFIED ORA FCtBFLG,X STA FCBFLG,X ; JMP GREAT ; DONE ; PUTER JMP ERDVDC PEOF JMP ERREOF .PAGE 'BURST I/O' ; ; TEST BURST I/O AND DO IF POSSIBLE ; WTBUR LDA FCBFLG,X ; IF NOT ACQUIRINGu SECTORS BPL NOBURST ; THEN UPDATE AND BMI TBURST ; NO BURST ; RTBUR LDA #0 ; SET READ TYPE ; TBURST STA BURTYP ; SET BURST TYPE LDA ICCOMZ ; IF COMMAND v AND #2 ; IS TEXT MORE BEQ NOBURST ; THEN NO BURST ; JSR TBLEN ; IF USER BUFFER LESS BCS NOBURST ; THEN SECTOR, NO BURST ; LDA ICBALZ ; MOVE USER BUFFEwR STA ZSBA ; ADR TO SECTPOR LDA ICBAHZ ; BUFFER PTR STA ZSBA+1 ; NXTBUR LDA BURTYP ; GET I/O TYPE BMI WRBUR ; BR IF WRITE ; JSR RDNXTS ; DO xSECTOR READ BCC BBINC ; BR IF EOF BCS BUREOF ; BR RD EOF ; NOBURST SEC ; INDICATE NO BURST RTS ; WRBUR LDA DRVMDL ; WRITE FULL SECTOR STA FCBDLN,X ;y DATA COUNT ; TAY LDA (ZSBA),Y ; SAVE DATA TO BE STA SVD1 ; TO BE CLOBBERED INY LDA (ZSBA),Y ; BY WRTNXS STA SVD2 INY LDA (ZSBA),Y STA z SVD3 ; JSR WRTNXS ; WRITE SECTOR ; LDY DRVMDL ; RESTORE CLOBBERED DATA LDA SVD1 STA (ZSBA),Y INY LDA SVD2 STA (ZSBA),Y INY LDA SVD3{ STA (ZSBA),Y ; ; BBINC CLC LDA ZSBA ; INC SECTOR ADC FCBMLN,X ; BUFFER ADR BY STA ZSBA ; ACTUAL DATA LEN LDA ZSBA+1 ; GOT OT PUT ADC #0 | STA ZSBA+1 ; SEC LDA ICBLLZ ; DEC USER SBC FCBMLN,X ; BUFFER LEN BY STA ICBLLZ ; ACTUAL DATA LEN LDA ICBLHZ ; GOT OR PUT SBC #0 NOP } STA ICBLHZ ; JSR TBLEN ; IF USER BUF LEN BCC NXTBUR ; NOW >= SECTOR, DO AGAIN ; BUREOF = * ; END OF BURSTING LDA ZSBA ; MOVE FINAL ADR BACK STA I~CBALZ ; TO USER BUFFER PTR LDA ZSBA+1 STA ICBAHZ ; LDY FCBBUF,X ; RESTORE ZSBA DEY JSR SSBA ; BURST CLC ; INDICATE BURSTED RTS  ; AND RETURN ; ; TEST USER BUF LEN FOR BURST ; TBLEN = * LDA DRVTYPE ; IF DRIVE NOT CMP #1 ; 128 BYTE SECTOR TYPE BNE TBL256 ; THEN DO 256 BYTE TEST ; LDA ICBLLZ ; IF 128 , MUST BY 128 BMI BURST ; OR MORE BYTES ; TBL256 LDA ICBLHZ ; IF BUF LEN HI >=256 BNE BURST ; THEN CAN BURST SEC ; ELSE INDICATE NO BURST RTS  .PAGE 'GET BYTE' ; ; ; DFMGET - GET A FILE BYTE ; DFMGET = * JSR SETUP ; GO SET UP LDA FCBOTC,X ; IF OPEN FOR AND #OPDIR ; DIR CNT BEQ GET1 JMP GDCHAR ; THEN GO TO DIR ROUTINE ; GET1 LDA FCBDLN,X ; GET DATA LENGTH CMP FCBMLN,X ; TEST EMPTY SECTOR BCC GET2 ; BR IF NOT EMPTY JSR RTBUR ; DO BURST IF POSSIBLE  JSR RDNXTS ; GET NEXT SECTOR BCC GET1 ; BR IF NOT EOF GEOF = * JMP ERREOF ; ELSE EOF ERROR ; GET2 TAY LDA (ZSBA),Y ; GET DATA BYTE STA SVDBYT ; SAVE THE BYTE INY ; INC DATA LENGTH TYA STA FCBDLN,X ; AND SET NEW VALUE EFLOOK = * LDY FCBLSN,X ; DO EOF LOOK AHEAD BNE GET3 ; IF LSN NOT ZERO  LDY FCBLSN+1,X ; THEN BNE GET3 ; NOT EOF CMP FCBMLN,X ; IF LSN=0 THEN CHECK FOR BCC GET3 ; LAST BYTE LDA #$03 ; IF LAST BYTE THEN RTN JMP RETURN ; GET3 JMP GREAT .PAGE 'STATUS' ; ; DFMSTA - GET A FILE STATUS ; DFMSTA JSR SETUP ; SET UP JSR FNDCODE ; DECODE FILE NAME JSR SFDIR ; SEARCH FOR FILE BCS  SFNF ; BR NOT FOUND JSR TSTLOCK ; TEST LOCKED JMP GREAT ; FILE EXISTS & UNLOCKED ; SFNF JMP ERFNF .PAGE 'CLOSE' ; ; DFMCLOSE - CLOSE A FILE ; DFMCLS JSR SETUP  ; SET UP LDA FCBOTC,X ; GET OPEN CODE AND #OPOUT ; IF NOT OUTPUT 995 BEQ CLDONE ; THEN DONE 996 ;  997 ROL FCBFLG,X ; IF NOT ACQUIRING SECTORS 998 BCC CLUPDT ; THEN IS UPDATE 999 ;  1000 JSR WRTLSEC ; WRITE LAST SECTOR 1001 ; 1002 JSR RRDIR ; GO GET DIRECTORY  1003 LDA FCBCNT+1,X ; GET COUNT OF SECTORS 1004 PHA 1005 LDA FCBCNT,X 1006  PHA 100 ; 1008 LDA FCBOTC,X ; GET OPEN CODE 1009 AND #OPAPND ; IF NOT APPEND 1010 BEQ CLOUT ; BR 1011 ; 1012 JSR DFRDSU ; ELSE SET UP FOR READ 1013 APP1 JSR RDNXTS ; READ TO EOF 1014 BCC APP1 ; C=SET ON EOR 1015 ;  1016 LDA FCBSSN,X ; MOVE START SECTOR 1017 STA FCBLSN,X ; TO EOF LINK SECTOR 1018 LDA FCBSSN+1,X  1019 STA FCBLSN+1,X 1020 JSR WRTN2 ; THEN WRITE AS NOT EOF 1021 ; 1022 CLOUT LDY CDIRD ; GET DIR DISPL 1023 CLC ; ADD DIR COUNT 1024 PLA ; TO ACQUIRE COUNT 1025 ADC FILDIR+DFDCNT,Y ; AND PUT BACK 1026 STA FILDIR+DFDCNT,Y 1027 PLA 1028 ADC FILDIR+DFDCNT+1,Y  102 STA FILDIR+DFDCNT+1,Y 1030 ; 1031 LDA #DFDINU+DFDNLD ; SET ENTRY TO IN-USE STA FILDIR+DFDFL1,Y 1033 JSR WRTDIR ; WRITE DIRECTORY 1034 JSR WRTVTOC ; WRITE VTOC 1035 ;  1036 CLDONE LDA #0 ; CLEAR OPEN CODE 1037 STA FCBOTC,X 1038 JMP FGREAT ; DONE 1039 ; 1040 CLUPDT = * ROL FCBFLG,X ; IF SECTOR NOT MODIFIED 1042 BCC CLDONE ; THEN DONE 1043 JSR WRCSIO ; ELSE WRITE IT 1044 JMP CLDONE ; THEN DONE 1045 ;  1046 .PAGE ; 1048 ; RE-READ DIR RECORD 1049 ;  1050 RRDIR = * 1051 LDA FCBFNO,X ; GET FILE NUMBER 1052 LSR A ; RE-ADJUST IT  105 LSR A 105 STA SFNUM ; PUT INTO SFNUM 1055 ;  1056 ; 1057 JSR FNSHFT ; SET ACU = FILE NO./64 1058 STA CDIRS ; TO GET DIR SECTOR 1059  JSR FNSHFT ; SET ACU TO REM * 16 1060 JSR FNSHF1 1061 ASL A 106 STA CDIRD ; TO GET DIR DISPL 1063 ; 1064 JMP RDDIR 1065 FNSHFT LDA #0  1066 FNSHF1 LDY #3 ; SHIFT 3 BITS OF 1067 FNSHF2 ASL FCBFNO,X ; FILE NO INTO ACU 1068 ROL A  106 DEY 1070 BNE FNSHF2 1071 RTS  1072 .PAGE 'DEVICE DEPENDENT COMMAND' ; ; DFMDDC - DEVICE DEPENDENT CMND EXECUTION ; DFMDDC JSR SETUP ; SET UP FOR EXECUTION LDA ICCOM,X ; GET COMMAND CMP #254 ; IS IT FORMAT BEQ XFV ; BR IF CMP #MAXDDC ; TEST RANGE BCS DVDCER ; BR OUT OF RANGE SEC SBC #$20 ; SUBTRACT $20 BCC DVDCER ; BR OUT OF RANGE ASL A ; MULT RESULT BY 2 TAY ; USE AS INDEX LDA DVDCVT,Y PHA ; PUSH EXECUTION ADR LDA DVDCVT+1,Y PHA ; TO STACK AND GOTO RTS ; VIA RTS ; DVDCVT .DBYTE XRENAME-1 ; 20 - RENAME .DBYTE XDELETE-1 ; 21 - DELETE .DBYTE DVDCER-1 ; INVALID CMND .DBYTE XLOCK-1 ; 23 - LOCK .DBYTE XUNLOCK-1 ; 24 - UNLOCK .DBYTE XPOINT-1 ; 25 - POINT .DBYTE XNOTE-1 ; 26 - NOTE ; MAXDDC = $27 ; MAX DVDC PLUS 1 ; DVDCER JMP ERDVDC XFV JMP XFORMAT ; FORMAT VECTOR .PAGE 'RENAME' ; ; XRENAME - RENAME A FILE OR FILES ; XRENAME JSR FNDCODE ; DECODE FILE NAME STY TEMP2 ; SAVE FNAME INDEX JSR SFDIR ; GO FIND FILE IN DIR BCC XRN1 ; BR IF FOUND JMP ERFNF ; XRN1 JSR TSTLOCK ; TEST LOCK JSR TSTDOS ; IF NOT DOS BNE XRN1A ; THEN JSR DELDOS ; DON'T CHANGE S0 XRN1A LDY TEMP2  ; GET INDEX FOR END FN1 JSR FNDCNX ; GO DECODE NEXT FILE NAME JSR TSTDOS ; IF NOT DOS BNE XRN1B ; THEN LDY CDIRD LDA FILDIR+DFDSSN+1,Y PHA LDA FILDIR+DFDSSN,Y TAY ; A,Y NEW DOS PLA ; START SECTOR JSR SETDSO ; GO WRITE SECTOR 0 ; XRN1B LDX #0 LDY CDIRD ; XRN2 LDA FNAME,X ; MOVE FILE NAME CMP #'? ; FROM FNAME TO DIR ENT BEQ XRN3 ; BUT DON'T CHANGE WILD CARD STA FILDIR+DFDPFN,Y ; CHARS INDICATED IN FNAME XRN3 INY INX CPX #11 BCC XRN2  LDX CURFCB ; RESTORE X-REG ; JSR WRTDIR ; GO WRITE CUR DIR RECORD ; JSR FNDCODE ; GET OLD FILE NAME AGAIN JSR CSFDIR ; CONTINUE SEARCH OF DIR BCC XRN1 ; BR IF FOUND ANOTHER ; JMP FGREAT ;GO TO GOOD ENDING .PAGE 'DELETE' ; ; XDELETE - DELETE ALL FILE NAME THAT MATCH ; XDELETE JSR FNDCODE ; GO DECODE FILE NAME 1148 JSR  SFDIR ; SEARCH DIR FOR FILE NAME 1149 BCS DFNF ; BR NOT FOUND 1150 XDELX = * 1151 JSR XDEL0  1152 JSR TSTDOS BNE XDELY JSR DELDOS XDELY ; 1153 XDEL3 JSR WRTDIR ; WRITE DIR ENTRY  1154 JSR CSFDIR ; LOOK FOR NEXT MATCH 1155 BCC XDELX ; BR IF FOUND 1156 JSR WRTVTOC  1157 JMP FGREAT 1158 ; 1159 XDEL0 JSR OPVTOC ;  1161 XDEL1 LDY CDIRD ; GET DIR DISPL 1162 JSR TSTLOCK ; GO TEST LOCK 1163 LDA #DFDEDE ; LOAD DELETED FLAG 1164 STA FILDIR+DFDFL1,Y ; DELETE FILE 1165 ; 1166 JSR DFRDSU 1167 JMP  XDEL2A 1168 ; 1169 XDEL2 JSR RDNXTS ; READ NEXT SECTOR 1170 BCS XDEL4  1171 XDEL2A = * JSR FRESECT ; FREE CURRENT SECTOR 1173 JMP XDEL2 1174 ; XDEL4 = * LDY #DVDWRQ ; TURN ON WRITE REQ'D LDA #$FF ; ON VTOC BUFFER STA (ZDRVA),Y RTS 1176 ;  1177 DFNF JMP ERFNF ; FILE NOT FOUND 1178 .PAGE 'LOCK AND UNLOCK' ; ; XLOCK - LOCK A FILE ; XUNLOCK - UNLOCK A FILE ; XLOCK LDA #DFDLOC ; SET LOCK  STA TEMP4 BNE XLCOM ; GO TO COMMON XUNLOCK LDA #0 ; SET UNLOCK STA TEMP4 ; XLCOM JSR FNDCODE ; DECODE FILE NAME JSR SFDIR ; FIND FIRST MATCH  BCC XLC1 ; BR MATCH FOUND JMP ERFNF ; BR NOT FOUND ; XLC1 LDY CDIRD ; GET CURRENT DISPL LDA FILDIR+DFDFL1,Y ; GET LOCK BYTE AND #$DF ; TURN OFF LOCK ORA  TEMP4 ; OR IN LOCK/UNLOCK STA FILDIR+DFDFL1,Y ; SET NEW LOCK BYTE JSR WRTDIR ; GO WRITE ; JSR CSFDIR ; LOOK FOR NEXT MATCH BCC XLC1 ; BR FOUND JMP FGREAT ;ELSE DONE ; ; TSTLOCK - TEST FILE LOCKED ; TSTLOCK LDY CDIRD ; GET DIR DISPL LDA FILDIR+DFDFL1,Y ; LOAD LOCK BYTE AND #DFDLOC ; MASK LOCK BIT BNE TLF ; BR IF LOCKED RTS ; ELSE RETURN ; TLF JMP ERFLOCK .PAGE 'POINT' ; ; XPOINT - POINT REQUEST ; XPOINT LDA FCBFLG,X ; IF ACQ SECTORS BMI PERR1 ; POINT INVALID LDA ICAUX4,X ; IF REQUEST IS NOT CMP FCBCSN+1,X ; SAME AS CURRENT BNE XP1 ; THEN BR LDA ICAUX3,X CMP FCBCSN,X BEQ XP2 ; ELSE NO NEED TO CHANGE ; XP1 LDA FCBFLG,X ; IF NOT MODIFIED BEQ XP1A ; BR JSR WRCSIO ; ELSE WRITE IT LDA #0 STA FCBFLG,X XP1A = * LDA ICAUX4,X STA FCBLSN+1,X LDA ICAUX3,X STA FCBLSN,X JSR RDNS0 ; READ REQ SECTOR BCS XPERR ; XP2 LDA ICAUX5,X ; TEST REG DATA LENGTH CMP FCBMLN,X ; LESS THAN MAX BCC XP3 BEQ XP3 XPERR = * JMP ERRPDL ; IF NOT, THEN ERROR ; XP3 STA FCBDLN,X ; SET NEW DATA LENGTH JMP GREAT ; DONE ; PERR1 JMP ERRPOT ; INVALID POINT OPEN .PAGE 'NOTE' ; ; XNOTE - EXECUTE NOTE REQUEST ; XNOTE LDA FCBDLN,X ; DATA LENGTH VALUE STA ICAUX5,X ; TO AUX 2 LDA FCBCSN,X ; CUR SEC NO (LOW) STA ICAUX3,X ; TO AUX 3 LDA FCBCSN+1,X  ; CUR SEC NO (HIGH) STA ICAUX4,X ; TO AUX 4 JMP GREAT ; DONE .PAGE 'FORMAT' ; ; XFORMAT - FORMAT A DISKETTE ; XFORMAT LDA ZSBA+1 ; MOVE VTOC BUF ADR STA DCBBUF+1  ; TO DCB LDA ZSBA STA DCBBUF LDA #DCBCFD ; FORMAT STA DCBCMD ; TO DCB LDA #$40 ; TELL SIO RECEIVING DATA STA DCBSTA LDX DRVTYP  ; GET DRIVE TYPE - 128 OR 256 LDA #$31 ; BUS ID LDY DSKTIM ; GET FORMAT TIME OUT VALUE JSR DSIO2 ; GOTO LOCAL DISK HANDLER- THEN SIO ; BPL XF0 IF NO ERRORS CONTINUE FORMAT CPY #$90 ELSE CHECK FOR A DEVICE DONE ERROR BNE XFERR NO, THEN ERROR EXIT ; TSTFMT = * ELSE CHECK FOR BAD SECTOR INFO LDY #0 RETURNED BY CONTROLLER  LDA #$FF CMP (ZSBA),Y BNE XFBAD BAD SECTORS, RETURN ERR MSG INY CMP (ZSBA),Y BEQ XFERR NOT BAD SECTOR ERR, REG ERR EXIT XFBAD JMP ERDBAD ; XFERR LDA DCBSTA  GET ERROR STATUS JMP RETURN DO ERROR EXIT ; XF0 LDA #0 TAY XF1 STA (ZDRVA),Y INY BPL XF1 ; LDY #0 ; SET LDA #2 ; TYPE = 2  STA (ZDRVA),Y INY LDA #$C3 ;SET MSN AND STA (ZDRVA),Y ;NSA = 707 = 2C3 INY INY STA (ZDRVA),Y LDA #$02 DEY STA (ZDRVA),Y INY  INY STA (ZDRVA),Y ; LDY #DVDSMP LDA #$FF ; SET SECTOR MAP TO XF2 STA (ZDRVA),Y ; ALL ONES INY CPY #DVDSMP+90 BNE XF2 ; LDA #$0F ; DEALLOCATE FIRST 4 SECTORS LDY #DVDSMP ; FOR BOOT STA (ZDRVA),Y ; LDY #DVDSMP+45 ; DEALLOCATE MIDDLE 9 LDA #0 ; SECTORS STA (ZDRVA),Y ; FOR INY  ; VTOC & FILE DIR LDA #$7F STA (ZDRVA),Y ; JSR WRTVTOC ; WRITE THE VTOC ; LDA #0 ; ZERO FILL DIRECTORY SECTORS TAY XF3 STA FILDIR,Y ; USE FILE DIRECTORY BUFFER INY BPL XF3 ; LDA #7 ; WRITE TO ALL 8 DIRECTORY SECTORS STA CDIRS XF4 JSR WRTDIR DEC CDIRS BPL XF4 ; JSR DELDOS ; SET NO DOS ; JMP FGREAT ;DONE .PAGE 'LIST DIRECTORY' ; ; LISTDIR - LIST THE DIRECTOR ; GDCHAR - GET NEXT DIR CHARACTER ; ; THE DIRECTORY IS LISTED VIA OPEN ; LIST DIRECTORY FUNCTION. EACH DIR ;  ENTRY THAT MATCHES THE FILE SPEC ; IS CONVERTED TO A PRINTABLE FORMAT ; INTO A SECTOR BUFFER. THE GET BYTE ; ENTRY IS USED TO GET THE PRINTABLE ; CHARACTERS ONE AT A TIME. THE ;  LAST LINE PRINTED IS ALWAYS A ; COUNT OF THE NUMBER OF SECTORS IN USE ; AND THE NUMBER REMAINING AVAIABLE SECTORS. ; LISTDIR LDA #0 STA TEMP4 JSR SFDIR ; SEARCH FOR A FILE NAME  BCC LDENT1 ; BR IF FOUND BCS LDCNT ; BR IF NOT FOUND ; GDCHAR BIT TEMP4 ; TEST FLAG BMI LDDONE ; BR IF ALL DONE ; LDY TEMP4 ; GET COUNT OF CHARS SENT LDA (ZSBA),Y ; GET NEXT CHAR STA SVDBYT ; IN SVDBYT INC TEMP4 ; INC COUNT CMP #EOL ; TEST IF EOL DONE BNE GDCRTN ; BR NOT EOL CPY #17 ; WAS THIS AN ENTRY BCS LDENT ; BR IF IF WAS LDA #$80 ; ELSE INDICATE END STA TEMP4 ; IN TEMP4 ; GDCRTN JMP GREAT ; DONE ; LDENT LDA #0 ;CLEAR CHAR COUNTER STA TEMP4 JSR CSFDIR ;SEARCH FOR NEXT MATCH BCS LDCNT ;BR NO MORE MATCHES LDENT1 JSR FDENT ;FORMAT ENTRY JMP GREAT ;DONE ; LDCNT JSR  RDVTOC ;READ VTOC LDY #DVDNSA+1 ;GET NUMBER SECTOR AVR LDA (ZDRVA),Y PHA DEY LDA (ZDRVA),Y TAY PLA ; JSR CVDX ;AND CONVERT ; LDY #3 ; SET EOL LDX #FSCML-1 ; PUT IN CUTE MVFSCM LDA FSCM,X ; MSG STA (ZSBA),Y INY DEX BPL MVFSCM JSR CVDY ; LDA #0 ;SET CHAR COUNT  STA TEMP4 JMP FGREAT ;DONE ; LDDONE JMP ERREOF ; END OF FILE ; FSCM .BYTE 'SROTCES EERF ' FSCML = *-FSCM .PAGE ; ; FORMAT DIR ENTRY INTO A SECTOR BUFFER ; FDENT LDY  #0 ;START AT BUF DISPL 0 LDA #$20 ;START WITH A BLANK STA (ZSBA),Y LDX CDIRD LDA FILDIR+DFDFL1,X AND #DFDLOC ; BUT IF FILE LOCKED BEQ LD1 LDA #'* ;CHANGE TO AST STA (ZSBA),Y LD1 INY LDA #$20 ;FOLLOWED BY A BLANK STA (ZSBA),Y INY ; LD2 LDA FILDIR+DFDPFN,X ;MOVE THE 12 CHAR STA (ZSBA),Y ;FILE NAME INX INY CPY #13 BCC LD2 ; LDA #$20 ;FOLLOWED BY A BLANK STA (ZSBA),Y INY STY TEMP4 ;SAVE INDEX = 15 ; LDX CDIRD LDY FILDIR+DFDCNT,X ;SET A,Y LDA FILDIR+DFDCNT+1,X ; = SECTOR COU(T ; CVDX LDX #100 ;CONVERT AND MOVE JSR CVDIGIT ;100S DIGIT LDX #10 JSR CVDIGIT ;10S DIGIT TYA  JSR STDIGIT ;1S DIGIT ; LDY #17 ; THEN PUT OUT CVDY LDA #EOL ;AND EOL STA (ZSBA),Y LDY #0 ; SET CHAR CNT =0 STY TEMP4 RTS  ;DONE FORMAT ; CVDIGIT STX TEMP3 ;SAVE DIGIT VALUE LDX #$FF ; CVD1 STA TEMP2 ;SAVE CUR VALUE HI STY TEMP1 ;AND LOW INX ;INC DIGIT COUNTER SEC  ;SUBTRACT DIGIT VALUE LDA TEMP1 ;FROM CUR VALUE SBC TEMP3 TAY LDA TEMP2 SBC #0 BCS CVD1 ;IF NOT GONE MINUS, DO AGAIN ; TXA  ;DIGIT TO ACU STDIGIT ORA #$30 ;PLUS ASCII ZERO LDY TEMP4 ;GET OUTPUT INDEX STA (ZSBA),Y ;AND SET DIGIT INC TEMP4 ;INC OUTPUT INDEX LDA TEMP2 ;LOAD VALUE HI LDY TEMP1 ;AND VALUE LOW RTS ;AND RETURN .PAGE 'FILE NAME DECODE' ; ; FNDCODE - DECODE A FILE NAME ; THE USER FILENAME IS POINTED TO BY ; ZBUFP, IT IS OF THE FORM P.X WHERE P ; IS THE PRIMARY FILE NAME (1 TO 8 CHARS) ; AND X IS THE EXTENDED FILE NAME ; (0 TO 4 CHARS). THE PERIOD IS OPTIONAL ; (IF NOT PRESENT, THEN NO EXTENSION). THE ;  DECODED FILE NAME WILL BE 12 CHHARS ; IN LENGTH. THE P FIELD WILL BE ; LEFT JUSTIFIED IN THE FIRST 8 BYTES. THE ; X FIELD WILL BE LEFT JUSTIFIED IN THE LAST ; 4 BYTES. BLANKS ARE USED TO PAD THE ; FIELDS TO FULL SIZE. IF THE USER SPECIFIED ; P OR X FIELDS CONTAIN MORE THEN 8 OR 4 ; CHARS, THAN THE EXTRA CHARS ARE IGNORED. ; THE '*' WILD CARD CHAR WILL CAUSE THE ; REST OF THE FIELDS TO BE FILLED WITH THE ; '?' WILD CARD CHAR. ANY NON-ALPHANUMERIC ; CHARACTER TERMINATES THE FILENAME. ; FNDCODE LDA ICBAL,X STA ZBUFP LDA ICBAH,X STA ZBUFP+1  LDY #2 ;FIND THE D FD0A LDA (ZBUFP),Y ; DEY BMI FDNERR ;BR IF 256 CHARS SEEN CMP #': BNE FD0A FD0B INY ; FNDCNX LDX #11 ; CLEAR FILENAME TO BLANKS LDA #$20 FD0 STA FNAME,X DEX BPL FD0 ; LDX #0 ; SET FNAME CHAR COUNT = 0 STX EXTSW ; SET NOT IN EXTENSION ; ; FD1 INY ; INC ZBUFP INDEX LDA (ZBUFP),Y ;GET BUFFER CHAR ; CMP #'* ; TEST FOR WILD CARDS BNE FD3 ; BR NOT WILD CARD ; FD2 LDA #'? ; LOAD ? WILD CARD JSR FDSCHAR ; GO STORE IT BCC FD2 ; BR IF PORX NOT FULL BPL FD1 ; BR IF AT START OF X BMI FDEND ; BR IF AT X END ; FD3 CMP #'. ; WAS CHAR FIELD SEPERATOR BNE FD4  ; BR IF NOT BIT EXTSW ; WAS THERE ALREADY ONE PERIOD BMI FDEND ; BR IF WAS (END) LDX #8 ; ADV FNAME INDEX TO X FIELD ROR EXTSW ; SET EXTSW = MINUS BCC FD1 ; CONTINUE WITH NEXT CHAR ; FD4 CMP #'? ; WAS IT WILD CARD BEQ FD6 ; BR IF WILD CARD ; CMP #'A ; IS CHAR ALPHA BCC FD5 ; BR NOT ALPHA  CMP #$5B ; TEXT HI ALPHA BCC FD6 ; BR IF ALPHA ; CHAR NOT ALPHA FD5 CPX #0 ; IF FIRST CHAR NOT BEQ FDNERR ; ALPHA THEN ERROR ; CMP #$30 ;IS CHAR NUMERIC BCC FDEND ; BR NOT NUMERIC (END OF NAME) CMP #$3A ;TEST NUMERIC HI BCS FDEND ; BR NO NUMBER ; FD6 JSR FDSCHAR ; STORE THE CHAR  JMP FD1 ; AND CONTINUE WITH NEXT ; FDEND LDX CURFCB ; RESTORE X REG RTS ; AND RETURN ; FDNERR JMP ERRFN ; INDICATE FILE NAME ERROR .PAGE ; ; FDSCHAR - STORE FILE NAME CHAR ; ON ENTRY A = CHAR ; X = NEXT FN POSITION ; ON EXIT CARRY - SET IF FIELD FULL ; MINUS - IF START OF EXECTION ; PLUS - IF END OF EXECTION ; FDSCHAR CPX #8  ; AT EXTENSION BCC FDSC2 ; BR IF NOT BEQ FDSC1 ; BR IF FIRST CHAR OF ; CPX #12 ; AT END OF EXIT BCC FDSC2 ; BR NOT AT END RTS ; RTN : PLUS, CARRY SET ; FDSC1 BIT EXTSW ; DO NOT STORE CHAR UNLESS BMI FDSC2 ; PERIOD WAS SEEN RTS ; RTN : MINUS, CARRY SET ; FDSC2 STA FNAME,X ; SET CHAR INTO NAME INX ; INC TO NEXT CHAR CLC RTS ; RTN : CARRY CLEAR .PAGE 'DIRECTORY SEARCH' ; ; SFDIR - SEARCH FILE DIRECTORY ; CSFDIR - FILE DIRECTORY SEARCH ; ; THE FILE DIRECTORY IS SEARCHED FOR THE ; FILENAME IN FNAME. THE SEARCH STARTS ; AT THE CENTRAL SECTOR+1 AND WILL CONTINUE ; FOR UP TO A TOTAL OF EIGHT SECTORS. WHEN ; TESTING FOR FMANE MATCH, '?' FNAME. ;  CHARS WILL ALLWAYS MATCH THE CORESPONDING ; DIR FILE NAME CHAR. IF A MATCH IS FOUND ; CDIRS CONTAINS THE RELATIVE DIRECTORY SECTOR ; NUMBER (0 -7) AND CDIRD (AND THE Y REG) ; CONTAIN THE DISPLACEMENT OF THE ENTRY. AFTER ; A MATCH HAS BEEN FOUND, THE DIRECTORY CAN ; BE SEARCHED FOR ANOTHER MATCH VIA THE CSFDIR ; ENTRY POINT. IF A MATCH HAS NOT BEEN FOUND, ; THEN DHOLES AND DHOLED WILL POINT TO A ; DIRECTORY HOLE THAT CAN BE USED. IF DHOLES = FF ; THEN THE DIRECTORY IS FULL. THE CARRY ; IS RETURN CLEAR IF FILE FOUND, SET IF FILE ; NOT FOUND. ; SFDIR LDA #$FF  ; INIT TO -1 STA DHOLES ; DIR HOLE SECTOR STA CDIRS ; CUR DIR SECTOR STA SFNUM ; FILE NUMBER LDA #$70 ; INIT TO -16 (-ENTRY LENGTH) STA CDIRD  ; CUR DIR DISPL ; CSFDIR INC SFNUM CLC LDA CDIRD ; CDIRD = CDIRD + ENTRY LENGTH ADC #DFDELN BPL SFD2 ; IF RESULT < 128 THEN BR ; ELSE AT END OF DIR SECT INC CDIRS ; INC TO NEXT DIR SECTOR LDA #8 ; TEST END OF DIR CMP CDIRS BCC SFD1 ; BR NOT END BEQ SDRTN ; SFD1 JSR RDDIR ; READ THE NEXT DIR RECORD LDA #0 ; SET DIR DISPL = 0 ; SFD2 STA CDIRD ; SET NEW DIR DISPL TAY ; PUT DISPL IN Y AS INDEX ; LDA FILDIR+DFDFL1,Y ; GET FLAG 1 BEQ SFDSH  ; BR IF UNUSED (END OF USED ENTRIES) BMI SFDSH ; BR IF DELETED AND #DFDOUT ; IF OPEN OUTPUT BNE CSFDIR ; DON'T FIND IT ; ENTRY IN USE, TEST FOR MATCH  LDX #0 ; TEST MATCH ON 12 CHARS SFD3 LDA FNAME,X ; FILE NAME CHAR CMP #'? ; IF FNC IS WILD CARD BEQ SFD4 ; THEN IT MATCHES CMP FILDIR+DFDPFN,Y ; ELSE IT MUST MATCH FOR REAC BNE CSFDIR ; IF NOT MATCH THEN TRY NEXT SFD4 INX ; INC CHAR CNT INY CPX #11 ; TEST ALL BNE SFD3 ; AND CONTINUE CHECK ; CLC ; WE HAVE A MATCH BCC SDRTN ; SFDSH ; WE HAVE A HOLE LDA DHOLES ; IF DHOLES NOT MINUS BPL SFDSH1 ; THEN ALREADY HAVE A GOOD HOLE ; ELSE  LDA CDIRS ; MOVE CURRENT DIR SECTOR STA DHOLES ; AND CURRENT DIR DISPL LDA CDIRD ; TO HOLE SECTOR AND DISPL STA DHOLED LDA SFNUM ; SAVE HOLE STA DHFNUM ; FILE NUMBER ; SFDSH1 LDA FILDIR+DFDFL1,Y ; IF HOLE WAS A DELETED BMI CSFDIR ; ENTRY THEN CONTINUE ; ELSE WE ARE AT END OF SEC ; USED ENTRIES THUS FILE NOT FOUND SDRTN LDX CURFCB ; RESTORE X REG RTS ; AND RETURN .PAGE 'WRITE DATA SECTOR' ; ; WRTNXS - WRITE NEXT SECTOR ; WRTNXS LDA FCBFLG,X ; IF ACQUIRING SECTORS BMI  WRTN1 ; THEN NOT UPDATE ; ASL A ; IF SECTOR NOT MODIFIED BPL WRU1 ; THEN DON'T IT ; ASL A STA FCBFLG,X ; TURN OFF FLAG BITS JSR WRCSIO ; WRITE CURRENT SECTOR BMI WRNERR ; BR IF BAD I/O WRU1 JMP RDNXTS ; ELSE READ NEXT SECTOR ; WRTN1 JSR GETSECTOR ; GET A NEW SECTOR ; WRTLSEC LDA FCBDLN,X ; GET DATA LENGTH WRTLS1 LDY DRVLBT  ; INTO LAST BYTE STA (ZSBA),Y ; OF SECTOR ; WRTN2 LDA FCBLSN+1,X ; MOVE LINK SECTOR ORA FCBFNO,X ; PLUS FILE NUM LDY DRVMDL ; TO BYTES 126,127 STA (ZSBA),Y  ; OF SECTOR BUFF INY LDA FCBLSN,X STA (ZSBA),Y ; JSR WRCSIO ; WRITE SECTOR BPL WRTN5 ; BR NOT ERROR ; WRNERR LDA DCBSTA ; SAVE ERROR STATUS STA TEMP4 LDA #0 ; CLOSE FILE STA FCBOTC,X LDA TEMP4 ; RECOVER ERROR CODE JMP RETURN ; GO RETURN ; WRTN5 INC FCBCNT,X ; INC SECTOR CNT BNE WRTN6  INC FCBCNT+1,X WRTN6 JSR MVLSN ; LINK TO CUR LDA #0 STA FCBLSN,X ; LINK = 0 STA FCBLSN+1,X STA FCBDLN,X ; DLN = 0 LDA DRVMDL STA FCBMLN,X WRNRTS CLC RTS ; DONE ; WRCSIO SEC ; WRITE CUR SECTOR RWCSIO LDA FCBCSN+1,X LDY FCBCSN,X JMP DSIO ; MVLSN LDA FCBLSN,X ; MOVE LINK STA FCBCSN,X LDA FCBLSN+1,X STA FCBCSN+1,X RTS ; .PAGE 'READ DATA SECTOR' ; ; RDNXTS - READ NEXT SECTOR ; RDNXTS LDA FCBFLG,X ; IF NOT UPD MODE BEQ RDNS0 ; BR JMP WRTNXS ; ELSE WRITE FIRS\ RDNS0 = * LDA FCBLSN,X ; IF LSN NOT ORA FCBLSN+1,X ; ZERO BNE RDNS1 ; BR SEC ; ELSE EOF RTS RDNS1 JSR MVLSN  ; MOVE LINK TO CURRENT CLC ; READ JSR RWCSIO ; CURRENT SECTOR BMI RDIOER ; BR IF OK READ ; ELSE GO TO I/O ERROR ; LDY DRVMDL LDA (ZSBA),Y ; TEST FOR SAME AND #$FC ; FILE NO CMP FCBFNO,X BNE RDFNMM ; IF NOT, THEN ERR ; LDA (ZSBA),Y ; MOVE LINK SECTOR AND #$03 STA FCBLSN +1,X INY LDA (ZSBA),Y STA FCBLSN,X ; ; INY ; INC TO LEN BYTE LDA (ZSBA),Y ; GET LEN BYTE PHA ; SAVE IT LDA FCBSLT,X  ; GET SECTOR LEN TYPE BNE RDNS3 ; BR IF NEW TYPE ; PLA ; GET LEN BMI RDNS2 ; BR IF OLD SHORT SECTOR LDA #125 ; ELSE SET FULL SECTOR RDNS2 AND #$7F  ; TURN OFF MSB PHA ; BALANCE STACK ; RDNS3 PLA STA FCBMLN,X ; SET MAX LENGTH ; LDA #0 ; SET CUR DATA LENGTH = 0 STA FCBDLN,X CLC RTS  ; DONE RDIOER JSR ERRIO ; I/O ERROR RDFNMM ; FILE NUMBER MISMATCH LDA ICCOM,X CMP #$21 ; WAS THIS DELETE BEQ RDDELE ; BR IF DELETE JSR  ERFNMM ; BR NOT DELETE RDDELE SEC ; INDICATE EOF TO DELETE RTS .PAGE 'READ/WRITE DIR' ; ; RDDIR/WRDIR - READ/WRITE DIRECTORY ; RDDIR CLC ; SET READ BCC DIRIO ; WRTDIR SEC ; SET WRITE ; DIRIO PHP ; SAVE READ/WRITE LDA #.HIGH.FILDIR ; MOVE BUF ADR STA DCBBUF+1 ; TO DCB LDA #.LOW.FILDIR STA DCBBUF ; CLC LDA CDIRS  ; CDIRS+ ADC #$69 ; ((40*18)/2)+1 TAY ; INTO A,Y LDA #1 ; IS DIR SECTOR NO ADC #0 ; JMP DSYSIO ; GO DO SYSTEM I/O .PAGE 'READ/WRITE VTOC' ; ; RDVTOC/WRCTOC - READ/WRITE VTOC ; RDVTOC LDY #DVDWRQ ; IF WRITE REQD LDA (ZDRVA),Y BEQ RDVGO RTS RDVGO CLC ; SET READ BCC VTIO ; WRTVTOC WRVTOC LDY #DVDWRQ ; TURN OFF LDA #0 ;WRITE REQD STA (ZDRVA),Y SEC ; ; VTIO PHP ; SAVE R/W LDA ZDRVA+1 ; MOVE BUF ADR STA DCBBUF+1 ; TO DCB  LDA ZDRVA STA DCBBUF ; LDY #$68 ; READ SECTOR LDA #1 ; (40*18)/2 ; DSYSIO PLP DSYSIA LDX DRVTYP ; LOAD DRIVE TYPE JSR BSIO ; GO DO I/O BMI DSIOER ; BR IF ERROR RTS ; RETURN ; ; DSIOER CMP #DCBDER ; WAS IT DATA ERRR BEQ DEAD ; BR IF WAS JMP ERRIO ; ELSE USER PROBLEM ; DEAD JMP ERRSYS ; FATAL ERROR ; ; OPEN VTOC ; OPVTOC JSR RDVTOC ; READ IT JMP WRTVTOC ; THEN WRITE IT ; INSURES NOT PROTECTED .PAGE 'FREE SECTOR' ; ; FRESECT - FREE CURRENT SECTOR ; FRESECT LDA FCBCSN,X ORA FCBCSN+1,X BEQ FSRTS LDA #0 LDY #3 ; DIVIDE SECTOR # FS1 LSR FCBCSN+1,X ; BY 3 TO GET BYTE NO ROR FCBCSN,X ; IN THE SECTOR MAP ROR A ; WITH REM IN ACU DEY BNE FS1 ; LDY #5 FS2 ROR A ; TO FOR BYTE BIT NO DEY BNE FS2 ; TAY  ; BIT NO (0 TO 7) INTO Y LDA #0 SEC ; SHIFT IN A BIT FS3 ROR A ; TO PROPER LOCCATION DEY BPL FS3 PHA ; SAVE MASK LDA FCBCSN,X ; GET BYTE NO ADC #DVDSMP ; ADD OFFSET TO SMAP TAY ; RESULT IS VTOC INDEX ; PLA ; GET BIT MASK ORA (ZDRVA),Y ; OF BIT TO BITMAP STA (ZDRVA),Y ; AND SET RESULTS ; LDY #DVDNSA ; INC NO SECTORS AVAIL LDA (ZDRVA),Y CLC ADC #1 STA (ZDRVA),Y INY LDA (ZDRVA),Y ADC #0 STA (ZDRVA),Y ; FSRTS = * RTS ; DONE .PAGE 'GET SECTOR' ; ; GET SECTOR - GET A FREE SECTOR FOR USE IN FCB AT X REG. ; THE SECTOR NUMBER IS PLACED IN FCBLSN. ; ; THE SEARCH FOR A FREE SECTOR STARTS AT THE ; DVDSMP BYTE. SECTOR ARE NUMBERED SEQUENTIALLY ; FROM ZERO TO MAXSM WITH THE LEFT BIT ; OF THE DVDSMP BEING WITH ZERO. ; GETSECTOR LDY #DVDSMP-1 ;SET Y TO START MAP-1 ; GS1 INY ;INC SMAP INDEX CPY #90+DVDSMP ;AT END OF MAP BCS GSERR ;BR IF AT END LDA (ZDRVA),Y ;GET A MAP BYTE BEQ GS1 ;BR NO FREE SECTOR IN BYTE ; STY TEMP1 ;SAVE MAP INDEX  PHA ; DEC NO SECTORS AVAIL SEC LDY #DVDNSA LDA (ZDRVA),Y SBC #1 STA (ZDRVA),Y INY LDA (ZDRVA),Y SBC #0 STA (ZDRVA),Y ;  INY ; SET WRITE REQD LDA #$FF STA (ZDRVA),Y ; PLA LDY #$FF ;SET BIT COUNTER=-1 ; GS2 INY ;SHIFT MAP BYTE ASL A ;UNTIL A FREE SECTOR BCC GS2 ;FOUND STY TEMP2 ;SAVE BIT NUMBER GS3 LSR A ;AND SHIFT BYTE DEY ; BACK TO IT'S ORIGNAL BPL GS3 ;POSITION AND PUT  IT LDY TEMP1 ; BACK INTO THE MAP STA (ZDRVA),Y ; ; SEC ;SECTOR MAP BYTE LDA TEMP1 ;=DISPL-DVDSMP SBC #DVDSMP ; LDY #0 STY TEMP1 ! ;CLEAR SECT NO HI ; GS4 ASL A ;MULT REL SECTOR MAP ROL TEMP1 ;BYTE NO BY 8 INY CPY #3 BCC GS4 ; CLC ADC TEMP2 ;ADD BIT NO TO STA " FCBLSN,X ;SECTOR NUMBER LDA TEMP1 ;AND PUT INTO ADC #0 ;FCBLSN STA FCBLSN+1,X ; RTS ;DONE ; GSERR JMP ERRNSA ;NO SECTOR AVAIL .PAGE '#SETUP ROUTINE' ; ; SETUP - A ROUTINE USED FOR ALL COMMANDS TO SETUP FMS ; CONTROL CELLS TO ACESS A PARTICULAR FILE ; SETUP LDA #$9F ; INIT ERROR CODE STA ERRNO ; TO ZERO STX CU$RFCB ; SAVE FCB ; TSX ; SAVE ENTRY STACK INX INX STX ENTSTK ; LDX CURFCB ; GET CURRENT FCB LDY ICDNOZ ; MOVE DRIVE NO STY DCBDRV % ; TO DCB DEY ; DEC FOR ACCESS TO TABLES LDA DBUFAL,Y ; MOVE DRIVE BUFFER STA ZDRVA ; ADR TO ZZRO PAGE PTR LDA DBUFAH,Y STA ZDRVA+1 ; LDA DRVTBL,&Y ; GET DRIVE TYPE BEQ DERR1 ; BR IF NOT EXIST STA DRVTYP ; SAVE TYPE ; TAY ; MOVE MAX DATA LEN LDA DRVMDL,Y ; AND LAST SECTOR BYTE STA DRVMDL ' ; DISPL TO START OF LDA DRVLBT,Y ; TABLES STA DRVLBT ; LDY FCBBUF,X ; GET SECTOR BUF NO. DEY ; DEC TO ACCESS TBL BPL SSBA ; BR IF ONE IS ALLOCAT(ED ; LDY #0 ; IF NONE ALLOCATED GSB1 LDA SECTBL,Y ; TRY TO FIND ONE BEQ GSB4 ; BR ONE FOUND GSB2 INY ; DEC TRY COUNT CPY #16 BCC GSB1 ); BR MORE TO TRY ; GSB3 JMP ERRNSB ; NO SECTOR BUFFERS AVAIABLE ; GSB4 LDA DRVTYP ; FOUND ONE, IF 256 BYTES LSR A ; DRIVE NEED TO CONT BCS GSB5 ; BR NOT 256 BYTES I*NY ; ELSE TRY NEXT CONTIG CPY #16 ; TEST END OF BUFFERS BCS GSB3 ; AND BR IF NO MORE LDA SECTBL,Y ; ELSE SEE IF ITS THREE BNE GSB2 ; BR NOT FREE+ DEY ; LDA #$80 ; ALLOCATE SECOND OF TWO STA SECTBL+1,Y ; GSB5 LDA #$80 ; ALLOCATE FIRST OR ONLY STA SECTBL,Y TYA STA FCBBUF,X ; PUT BUF NO INTO FCB , INC FCBBUF,X ; INC BUF NO SO NOT ZERO ; SSBA LDA SABUFL,Y ; MOVE BUFFER ADR STA ZSBA ; TO ZERO PAGE PTR LDA SABUFH,Y STA ZSBA+1 ; ; RTS ; DERR1 JMP ERRDNO - ; BAD DRIVE NO .PAGE ; ; FREE SECTOR BUFFERS ; FRESBUF = * LDY FCBBUF,X ; GET BUF NO BEQ FSBR ; BR IF NONE DEY ; DEC FOR TBL ACCESS LDA #0 . ; FREE STA FCBBUF,X ; IN FCB STA SECTBL,Y ; AND TABLE LDA DRVTYP ; IF 128 BYTE LSR A ; DRIVE BCS FSBR ; FREE ONLY ONE LSR / A ; ELSE STA SECTBL+1,Y ; FREE TWO FSBR RTS .PAGE .PAGE 'DATA SECTOR I/O' ; ; DSIO - DATA SECTOR I/O ; DSIO PHA ; SAVE ACU DATA LDA ZSBA 0 ; WRITE SECTOR BUF STA DCBBUF ; ADR MOVED TO LDA ZSBA+1 ; DCB STA DCBBUF+1 PLA ; RESTORE ACU ; LDX DRVTYP JSR BSIO ; DO THE I/O 1 RTS .PAGE 'WRITE DOS' ; ; WRTDOS - WRITE DOS TO DISK ; WRTDOS LDY FCBCSN,X ; MOVE START ADR LDA FCBCSN+1,X JSR SETDSO ; WRITE SECTOR ZERO JSR WD0 ; WRITE DOS 2 JMP GREAT ; DELDOS LDA #0 ; SET FILE NOT EXISTS DD1 STA DFSFLG ; WRTSC0 LDA #.HIGH.FMSORG ; MOVE FMS START STA DCBBUF+1 ; ADR TO DCB LDA #.LOW.FMSORG STA 3 DCBBUF ; LDA #0 ; CLEAR SECTOR NO TO ZERO STA DCBSEC STA DCBSEC+1 ; WRNBS INC DCBSEC ; INC SECTOR NO. LDX #1 ; GET DRIVE TYPE SEC JSR BSIOR4 ; DO THE WRITE ; ; CLC LDA DCBBUF ; INC SECTOR ADDR ADC #128 STA DCBBUF LDA DCBBUF+1 ADC #0 STA DCBBUF+1 ; LDA DCBSEC ; TEST FOR WRI5TE CMP BRCNT ; OF ALL BOOT SECTORS BNE WRNBS ; BR NOT ALL ; RTS ; SETDSO STY DFLINK ; SET LINK START STA DFLINK+1 ; LDA DRVTYP STA DFSFLG 6 LDY DRVMDL STY BLDISP BNE DD1 ; GO WRITE SECTOR ZERO .PAGE WD0 LDA DFLADR ; MOVE FILE START ADR STA ZBUFP ; TO ZBUFP LDA DFLADR+1 STA ZBUFP+1 ;7 WD1 LDY #0 ; MOVE 125 WD2 LDA (ZBUFP),Y ; BYTES OF DOS STA (ZSBA),Y ; TO SECTOR BUFFER INY CPY DRVMDL BCC WD2 TYA STA FCBDLN,X ;SET DATA LE8NGTH ; JSR INCBA ; INCREMENT ZBUFP BY 125 CMP SASA+1 ; IF NOT END OR BCC WD3 ; PAST END OF DOS BNE WD4 ; THEN WRTNXS LDA ZBUFP ; ELSE 9 CMP SASA ; DONE BCC WD3 BNE WD4 ; WD3 JSR WRTNXS ; WRITE NEXT SECTOR JMP WD1 ; WD4 RTS ; RETURN, CLOSE WILL WRITE FINAL SECTOR ; : AND RETURN ; .PAGE 'TEST DOS FILE NAME' ; ; TSTDOS - TEST FOR DOS SYS FILENAME ; TSTDOS LDY #11 ; LOOK AT 12 CHARS TDF1 LDA FNAME-1,Y ; TEST DECODED FILE NAME CHAR CMP DFN-1,Y ; W;ITH DOS FILE NAME CHAR BNE TDFR ; BR NOT MATCH DEY BNE TDF1 ; BR IF MORE, ELSE RTN EQ TDFR RTS ; RETURN ; DFN .BYTE 'DOS SYS ' .PAGE 'ERROR ROUNTINES AND RETFNMM INC ERRNO ; FILE NUMBER MISMATCH ERRSYS INC ERRNO ;FATAL SYSTEM DATA I/O ERROR ERRNSA INC ERRNO ;NO SECTOR AVAIL ERRNSB INC ERRNO ;NO SECTOR BUFFERS AVAIL ERRDNO INC ERRNO ;?DRIVE NO ERROR ; LDA ERRNO ;GET ERROR NUMBER RETURN LDX CURFCB ;GET CUR FCB NO STA ICSTA,X ; PUT IN ICB LDX ENTSTK ;GET ENTRY STACK PTR TXS ;AND RES@TORE LDX CURFCB TAY LDA SVDBYT ;GET SAVED DATA BYTE RTS ;AND RETURN ; ERRIO LDA DCBSTA ;GET I/O ERROR CODE BMI RETURN ;AND RETURN ; FGREAT LDX ACURFCB JSR FRESBUF ; FREE SECTOR BUFFER GREAT LDA #01 ;SET ALL OK BNE RETURN ;AND RETURN ERREOF LDA #$88 ; SET EOF CODE BMI RETURN ; GO RETURN .PAGE B 'MISC STORAGE' ; ; MISC NON ZERO .PAGE STORAGE AREA ; DRVMDL .BYTE 0 ; MAX DATA LEN .BYTE 125 ; 128 BYTE SECTOR .BYTE 253 ; 256 BYTE SECTOR ; DRVLBT .BYTE 0 ; DISPL TO LAST SECCTOR BYTE .BYTE 127 ; 128 BYTE SECTOR .BYTE 255 ; 256 BYTE SECTOR DRVTYP *=*+1 ; DRIVE TYPE RETRY *=*+1 ; I/O RETRY COUNTER ENTSTK *=*+1 ;ENTRY STACK DLEVEL CURFCB *=*+1 ;CURRENT FCB (IOCB ALSO) DHOLES *=*+1 ; DIR HOLE SECTOR DHOLED *=*+1 ; DIR HOLE DISPL DHFNUM *=*+1 ; DIR HOLE FILE NO. CDIRD *=*+1 ; ECUR DIR DISPL CDIRS *=*+1 ; CUR DIR SECTOR SFNUM *=*+1 ; FILE NUMBER SVDBYT *=*+1 ; SAVED OUTPUT DATA BYTE SVD1 *=*+1 ; SAVE DATA BYTES SVD2 *=*+1 ; FFOR WRITE BURST SVD3 *=*+1 EXTSW ; FNDCODE EXTENSION FLAG TEMP1 *=*+1 ; TEMP1 TEMP2 *=*+1 ; TEMP2 TEMP3 *=*+1 ; TEMP3 TEMP4 *=*+1 ; TEM4 BURGTYP *=*+1 ; BURST I/O TYPE ; DRVTBL *=*+8 ; DRIVE TABLE SECTBL *=*+16 DBUFAL *=*+8 ; VTOC BUFFER DBUFAH *=*+8 ; PTR FOR DRIVE N SABUFL *=*+16 ; SECTOR BUFFH SABUFH *=*+16 ; FOR SECTOR N FNAME *=*+12 ;FILE NAME AFNAME *=*+12 ; AUXILLARY FILE NAME ; MDRV *=*+1 ; MAX DRIVE NO. ; Z = * *= $1381 ;PUT ON ISAME BOUNDARY AS PRODUCTION ;VERSION DONE ON 11/34 .PAGE 'FILE CONTROL BLOCKS' ; ; FILE CONTROL BLOCK ; ONE FILE CONTROL BLOCK IS USED FOR EACH ; OPEN FILE. THE RELATILE FCB USED ; RELATES JDIRECTLY TO THE IOCB NUMBER ; THAT OPENED THE FILE. THUS THERE ARE ; EIGHT FCBS. THE FCBS ARE(CONVIENTLY) ; THE SAME SIZE AS IOCBS. EACH FCB ; CONTAINS ALL THE IMFORMATION REQUIRED TO ; CONTROL THE PROCESSING OF AN OPEN FILKE ; FCB FCBFNO *=*+1 ;FILE NUMBER LEFT JUSTIFIED FCBOTC *=*+1 ;OPEN TYPE CODE *=*+1 ; SPARE FCBSLT *=*+1 ; FLAG FOR NEW SECTOR LEN TYPE FCBFLG *=*+1 ;WLORKING FLAG FCBMLN *=*+1 ; MAX SECTOR DATA LENGTH FCBDLN *=*+1 ;CURRENT SECTOR BUFFER DATA LENGTH FCBBUF *=*+1 ; SECTOR BUFFER NO FCBCSN *=*+2 ;CURRENT SECTOR NUMBER FCBLSN *=*M+2 ;LINK/ALLOCATE SECTOR NUMBER FCBSSN *=*+2 ; START SECTOR NU7BE[ (?A&PEN: FCBCRS ; CURRENT FILE RELATIVE SECTOR NUMBER FCBCNT *=*+2 ; SECTOR CNT FCBLEN = *-FCB N ;FCB LENGTH ; *=FCBLEN*7+* ; ALLOCATE 7 MORE FCBS ; ; OPEN CODE BITS ; - USED IN IOCB AUX1 ; - AND FCBOTC ; OPIN = $04 ; INPUT OPOUT = $08 ; OUTPUT OPDIR = O$02 ; LIST DIRECTORY OPAPND = $01 ; APPEND ; FCBFAS = $80 ; FCBFLG - ACQ SECTORS FCBFSM = $40 ; FCBFLG - SECTOR MODIFIED .PAGE 'FILE DIRECTORY' ; ; DISK FILE DIRECTORY ; P -THE FILE DIRECTORY OCCUPIES 8 CONSECUTIVE SECTORS ; STARTING AT THE CENTRAL SECTOR+1. EACH ; FILE DIRECTORY SECTOR CONTAINS EIGHT ENTRIES. ; THE IS ONE ENTRY FOR EACH NAMED FILE. THE ; ARE A TOTAL OF 64 NAMED FILES PER VOLUMQE ; ; THE FILE NUMBER IS USED THROUGH OUT THE ; SYSTEM IS THE RELATIVE (TO ONE) FILE ; DIRECTORY ENTRY NUMBER. ; ; THE EQUATES BELOW ARE FOR A SINCE NAMED FILE ENTRY ; DFDFL1 = 0 ;FLAG1 (1) DFDCNT = 1 R ; SECTOR COUNTER (LOW) DFDSSN = 3 ;START SECTOR NO. (2) DFDPFN = 5 ;PRIMARY FILE NAME (8) DFDXFN = 13 ;EXTENDED FILE NAME (4) DFDELN = 16 ;ENTRY LENGTH ; ; DSFDFL1 VALUE EQUATE ; DFDEUU = 0 ;ENTRY UNUSED DFDEDE = $80 ;ENTRY DELETED DFDINU = $40 ; ENTRY IN USE DFDOUT = $01 ;FILE OPEN FOR OUTPUT DFDLOC = $20 ; ENTRY LOCTKED DFDNLD = $02 ; FILE HAS NEW TYPE SECTOR LEN BYTE ; FILDIR *=*+256 ;RESUME FILE DIR SPACE .PAGE 'VOLUME DIRECTORY' ; ; ; ; DISK VOLUME DIRECTORY ; THE VOLUME DIRECTORY OCCUPIES THE CENTRAL ; U VOLUME SECTOR. THE VOLUME DIRECTORY CONTAINS ; INFORMATION PARTAINING TO THE ENTIRE ; DISKETTE VOLUME. ; ; THE LABELS BELOW MAP THE VOLUME ; DIRECTORY SECTOR. ; DVDTCD = 0 ;VOLUME DIRECTORY TYPE CODE (1) ;V ;USED TO DELINATE MAJOR (1) ; ;FMS SYSTEM FORMAT CHANGES ; DVDMSN = 1 ; MAX SECTOR NUMBER (2) DVDNSA = 3 ; NO SECTORS AVAIABLE ; DVDWRQ = 5 W ; WRITE REQUIRED DVDSMP = 10 ;SECTOR MAP START ; ;EACH BIT REPRESENTS ; ;A SECTOR. IF THE BIT ; ;IS ON THEN THE SECTOR ; X ;IS FREE AND AVAILABLE. IF ; ;THE BIT IS OFF, THE ; ;SECTOR IS IN USE OR ; ;BAD. THE MOST SIGNIFICANT ; ;BIT OF THE FIYRST BYTE IS ; ;SECTOR ZERO. ; .PAGE 'END OF FMS' ENDFMS = * .END ; REQUIRED TO INTERFACE WITH THE APPLE 13 SECTOR ; FORMAT DISK. THE DCB IS USED FOR COMMUNICATION ; Z WITH THE FILE MANAGEMENT SYSTEM. THE IOB ; IS USED TO COMMUNICATE WITH APPLES READ/WRITE ; TRACK SECTOR (OR 'KORE ROUTINES') ; *= DHADR A13SDH LDA DCBCMD ; LOAD DCB COMMAND CM[P #DCBCST ; TEST AT STATUS BNE ADFMT ; BR IF NOT STATUS ; ADGIO LDA #DCBSOK ; STATUS REQUEST STA DCBSTA ; REPORT OK RTS ; RETURN ; ADFMT \ ; FORMAT REQUEST CMP #DCBCFD BNE ADCRW ; BR NOT FORMAT LDA #IBCFD ; LOAD FORMAT COMMAND STA IBCMD JSR ADIO1 ; DO FORMAT LDA #IBCWS ; THE]N WRITE ALL SECTORS STA IBCMD LDA #34 STA IBTRK ADF2 LDA #12 STA IBSECT ADF1 JSR ADIO1 DEC IBSECT BPL ADF1 DEC IBTRK BPL ADF2 BMI A^DGIO ; ADCRW ; READ/WRITE REQUEST LDA #IBCRS STA IBCMD JSR CONVTS ; CONVERT ABS SECTOR NO TO ; ; APPLE TRACK/SECTOR STA IBTRK STY _ IBSECT JSR ADIO1 LDA DCBCMD LDY #IBCRS CMP #DCBCRS BEQ ADCRW1 LDY #IBCWS ADCRW1 STY IBCMD ; ; SO JUST SET IT ; ADIO LDA #IBCWS ` CMP IBCMD BNE ADIOX JSR ADWBUF ADIOX JSR ADIO1 ; BCS ADBIO ; BR IF BAD I/O ; LDA #80 ; GET BYTE COUNT = 128 STA DCBCNT LDA #0 STA DCBCaNT+1 LDA #IBCRS CMP IBCMD BNE ADGIO JSR ADRBUF JMP ADGIO ; ADBIO LDA IBSTAT ; GET AD STATUS ; LDX #DCBWRP ; TRY WRITE PROTECT CMP #IBSWP b BEQ ADBS ; BR IF WRITE PROTECT LDX #DCBDER ; ELSE IS READ ERROR ; ADBS STX DCBSTA ; SET READ ERROR LDA #0 ; SET BYTE COUNT =0 STA DCBCNT STA DCBCNT+c1 RTS ; DONE ; ; CONVTS - CONVERT ABS SECTOR TO TRACK/SECTOR ; - ACU = TRACK = ABS SECTOR/13 ; - Y = SECTOR = REM ; CONVTS LDA DCBSEC ; USE APPLES DIVIDE ROUTINE STdA $50 LDA DCBSEC+1 STA $51 LDA #$1A STA $54 LDA #0 STA $52 STA $53 STA $55 JSR $FB84 LDA $50 LSR $52 LDY e$52 RTS ADWBUF JSR ADBUF ADWB1 LDA ($50),Y STA ADSB,X INX INY BPL ADWB1 RTS ADRBUF JSR ADBUF ADRB1 LDA ADSB,X STA ($50),Y INX INY f BPL ADRB1 RTS ADBUF LDX #0 LDA DCBSEC ROR A BCC ADBUF1 LDX #$80 ADBUF1 LDY #0 LDA DCBBUF STA $50 LDA DCBBUF+1 STA $51 g RTS ; ADSB *=*+256 ADIO1 LDA DCBDRV ; MOVE DRIVE NUMBER STA IBDRVN LDA #0 ; SET TRACK = 0 STA IBVOL LDA #.HIGH.ADSB STA IBBUFP+1 LDA #.LOW.ADShB STA IBBUFP ; LDA #.HIGH.IOB LDY #.LOW.IOB JSR $BD00 ; GO DO I/O RTS .PAGE 'IOB' *= $B7E8 ; ; IOB - INPUT/OUTPUT BLOCK ; INTERFACE THE DISK HANDLiER TO ; THE APPLE 13 SECTOR RWTS ; IOB IBTYPE *=*+1 ; IOB TYPE CODE IBSLOT *=*+1 ; CONTROLLER SLOT NO IBDRVN *=*+1 ; DRIVE NO IBVOL *=*+1 ; VOLUME NO IBTRK j*=*+1 ; TRACK NUMBER IBSECT *=*+1 ; SECTOR NUMBER IBDCTP *=*+2 ; DEVICE CONTROL TABLE PTR IBBUFP *=*+2 ; BUFFER POINTERS IBDLEN *=*+2 ; DATA LENGTH IBCMD k *=*+1 ; COMMAND IBSTAT *=*+1 ; I/O STATUS IBSMOD *=*+1 ; STATUS MODIFIER IBPSLT *=*+1 ; PREVIOUS SLOT IBPDRV *=*+1 ; PREVIOUS DRIVE IBSPAR *=*+1 l ; SPARE ; ; IBCMD VALUE EQUATES ; IBCRS = $01 ; READ SECTOR IBCWS = $02 ; WRITE SECTOR IBCFD = $04 ; FORMAT DISK ; ; IBSTAT VALUE EQUATES ; IBSRE = $80 m; READ ERROR IBSDE = $40 ; DRIVE ERROR IBSWP = $10 ; WRITE PROTECT ; .ENDIF .PAGE 'GLOP' .END