@L}6CD l0C)HCC WhL/h `CmCDiD`  R@P1  Y0@R !L` D  C D     )16CS S)  C)D1 p p 0 C9DI pCDL~CiCDiD`X;SAVE #D9:FMSEQU.M656AFMS - Dual Density for Atari 1050 drives (2.50)A/A --- Copyright and Author Notice }---AX;X;,X; Copyright (c) 1978,1979,1980,1982,1984$.X; Optimized Systems Software, Incorporated.X; San Jose, Calif}ornia8X;B)X; THIS PROGRAM MAY NOT BE REPRODUCED,L&X; STORED IN A RETRIEVAL SYSTEM, ORV&X; TRANSMITTED IN WHOLE OR IN PAR}T,`)X; IN ANY FORM, OR BY ANY MEANS, BE ITj*X; ELECTRONIC,MECHANICAL, PHOTOCOPYING,t)X; RECORDING, OR OTHERWISE WITHOUT TH}E~!X; PRIOR WRITTEN PERMISSION OF+X; OPTIMIZED SYSTEMS SOFTWARE, INC.!X; 1221-B KENTWOOD AVENUE.X; SAN }JOSE, CALIFORNIA 95129 (U.S.A.)X;!X; PHONE: (408) 446-3099X;X;(X;***********************************X; }&X; Originally designed and coded by7X; Paul Laughton of Shepardson Microsystems, Inc.X;*X; Modified for Atari 105 }0 and 130XE by #X; Mark Rose & Bill WilkinsonX; of O.S.S., Inc.X;(X; January, 19852X;<X;F(X;******** }***************************PX;ZA System EquatesAd(X;***********************************nX;xX;+X; === Unive }rsal Atari OS Equates ===X;BOSBTM5 ;; OS ROMs always call FMS from $E000-$FFFF ???(FMSORG;; normal boot-}in location,FMSZPGC;; seven bytes reserved for FMSX;+IOCBORG@;; 8 IOCB's of 16 bytes each)ZICB ;; current }IOCB is copied hereLMASK;;LINK MASKX;&DCBORG;; command block for SIO"SIOVY;; vector for SIO callX;},DHADRS;; vector for resident disk I/O0DHSTAT;; where DHADR returns disk status4DSKTIMF;; format disk time }out (DHADR result)"X;,1PIABPORT;; data port, memory select, etc.6'EOL;; ATASCII "Return" character@7LMADR;}; pointer to bottom of application memoryJ)DEVTAB;; device name & addr tableTX;^!CRITICB;; critical I/O flagh2N}MIEN;; NMI disable/enable (1-bit enables)r,CLOCKLSB;; lowest byte of jiffy clock|X;X;6X; === Equates Preserve}d by FMS in all versions ===!SECVTOCh;; where regular V.EVSECNUM;; becuz DOS only uses to 1023X;+DUPINIT}@;; initial addr for mini-DUP-STAK;;stack offset of FMS caller addr,TIMOUT;; time out for normal disk I/OX;}'X; Size of VTOC in MFM mode on 1050:X;5VTOCSIZE;; 10 (header)+128 (bit map)+6 (evtoc)X;$X; LENGTH OF SECTOR A}ND NUMBER OFX; DATA BYTES:X;& DRVMDL}0 DRVLBT:X;DA IOCBAN IOCBORGXX;bX; IOCB - IO CONTROL BLO}CKl$X; THERE ARE 8 I/O CONTROL BLOCKSv!X; 1 IOCB IS REQUIRED FOR EACH#X; CURRENTLY OPEN DEVICE OR FILEX;IOCBIC}HID ;;DEVICE NUMBERICDNO ;;DEVICE HANDLERICCOM ;; I/O COMMANDICSTA ;;I/O STATUSICBAL  }ICBAH ;;BUFFER ADR (H,L) ICPUT ;;PUT CHAR DH ADDRICBLL  ICBLH ;;BUFFER LEN (H,L)ICAUX1 ;;AU}X 1ICAUX2 ;;AUX 2 ICAUX3 ;;AUX 3ICAUX4 ;;AUX 4 ICAUX5 ;;AUX 5*ICAUX6 ;;AUX 64ICLEN }IOCB>X;H( ICLEN;;SPACE FOR 7 MORE IOCB'SRX;\X; ICCOM VALUE EQUATESfX;pICOIN;;OPEN INPUTzICOOUT;;O}PEN OUTPUTICIO;;OPEN UN/OUTICGBR;;GET BINARY RECORDICGTR;; GET TEXT RECORDICGBC;;GET BINARY CHAR}ICGTC;;GET TEXT CHARICPBR;;GET BINARY RECORDICPTR ;;PUT TEXT RECORDICPBC ;;PUT BINARY CHARICPTC} ;;PUT TEXT CHAR ICCLOSE ;;CLOSE FILEICSTAT ;;GET STATUSICDDC;;DEVICE DEPENDENTICMAX;;MAX VALUE " }ICFREE;;IOCB FREE INDICATOR X; X; ICSTA VALUE EQUATES$ X;. $ICSOK;;STATUS GOOD, NO ERRORS8 ICSTR;;TRUNCAIAT!}ED RECORDB ICSEOF;;END OF FILEL ICSBRK;;BREAK KEY ABORTV ICSDNR;;DEVICE NOT READY` "ICSNED;;NON EXISTENT D"}EVICEj ICSDER;;DATA ERRORt ICSIVC;;INVALID COMMAND~ #ICSNOP;;DEVICE/FILE NOT OPEN ICSIVN;;INVALID IOCB ##} ICSWPC;;WRITE PROTECT ICSNAK;; NAK from device X; X; ZERO PAGE IOCB LABELS X; ICDNOZICDNOIOCBZICB$} &ICBLLZICBLLIOCBZICB;;BUF LEN ICBLHZICBLHIOCBZICB 'ICBALZICBALIOCBZICB;;BUF ADDR ICBAHZICBAHI%}OCBZICB ICCOMZICCOMIOCBZICB +ICPUTZICPUTIOCBZICB;;PUT RTN ADDR &ICAX1ZICAUX1IOCBZICB;; aux 1 A&} DCBA DCBORG( X;2 X; DCB - DATA CONTROL BLOCK< (X; THE DCB IS A CONTROL/COMMAND BLOCKF -X; USED TO INTERFACE TO SER'}IAL I/O DEVICESP -X; SUCH AS THE DISK DRIVE(S) FROM RESIDENTZ X; HANDLERS SUCH AS FMS.d X;n DCBx DCBSBI ;;SERIAL BU(}S ID DCBDRV ;;DISK DRIVE # DCBCMD ;;COMMAND DCBSTA ;;I/O STATUS &DCBBUF ;;I/O BUFFER ADDR (H,L) )}DCBTO ;;TIME OUT CNT DCBCNT ;;I/O BYTE COUNT "DCBSEC ;;I/O SECTOR NUMBER X; X; DCBCMD VALUE EQUATES X*}; $DCBCRS R;;Read sector ($52) $DCBCWS W;;Write sector ($50) $DCBCST S;;Status request ($53) $DCBCFD !;;F+}ormat Diskette ($21) *DCBCFMFM ";;Format MFM diskette ($22) X;" X; *** SPECIAL NOTE:, /X; DCBCWS may be change,}d to 'P ($50)6 -X; if desired to have disk DISABLE@ 2X; the verifying read after each write.J -X; Dis-}k write ('W) operations takeT ,X; longer, but are more reliable.^ .X; Put ('P) is much faster, though.h X;r .}X; DCBSTA VALUE EQUATES| X; DCBSOK;;STATUS NORMAL DCBDNR;;DEVICE NOT READY #DCBCNR;;CONTROLLER NOT READY /}DCBDER;;DATA ERROR DCBIVC;;INVALID COMMAND DCBWPR;;WRITE PROTECT DCBNAK;;NAK from device A ZER0}O PAGEA X; (X; Device drivers in general--and FMS ,X; in particular--are allocated seven (7) #X; temporary bytes in zero1} page. X; (X; A device can NOT assume that these 'X; bytes will survive intact between +X; CIO calls to the device drive2}r!2979 ;& FMSZPG0 X;: "ZBUFPICBALZ;; BUFFER POINTERD .ERPTR ;; HOLDS POINTER TO ERROR NUMBERN *VTOCPTR ;; po3}inter to current VTOCX 0ZSBA ;; pointer to current sector bufferb 4CURFCB ;; CURrent FCB number ($10,$20, etc.)l X4};v X; other uses of ERPTR X; &ZTEMP1ERPTR;; just a 1 byte temp )ZTEMP2ERPTR;; just a 1 byte temp BUFPTRZSB5}A;; a better name !ZDRVAVTOCPTR;; the old name X; "A Macros and Error CodesA X; )X; Macro for generating erro6}r returns: X; @ERROR ERROR    X; X; X; ERROR CODES* X;4 (E.DBAD;;BAD SECTOR AT FORMAT TIME> -E7}.APO;;ATTEMPT APPEND TO OLD TYPE FILEH E.POT;;POINT INVALIDR E.FNF;;FILE NOT FOUND\ E.DFULL;;DIRECTORY FULL8}f %E.DVDC;;DEVICE COMMAND INVALIDp E.FLOCK;;FILE LOCKEDz E.PDL;;POINT DATA LENGTH E.FN;;FILE NAME ERROR 9}#E.FNMM;;FILE NUMBER MISMATCH &E.SYS;;FATAL SYS DATA I/O ERROR E.NSA;;NO SECTOR AVAIL %E.NSB;;NO SECTOR B:}UFFERS AVAIL E.DNO;;DRIVE NO ERROR E.EOF;; END OF FILE ERROR $E.NAK;; ??? simulated NAK ??? X; X; $X; t;}he following MACRO is used to (X; ensure entry point compatibility $X; with original Atari DOS 2.0sX; @ORG   }]X;SAVE #D9:FMSBOOT.M65ABOOT RECORDA FMSORGX;$X; THE FOLLOWING BYTES ARE STORED$X; ON DISK SECTOR 0 THE=}Y COMPRISE$X; THE BOOT LOAD RECORD.X;8BFLG ;;BOOT FLAG UNUSED=0B0BRCNT ;;NO CONSECTIVE BOOT RECORDS TO READL"B>}LDADR FMSORG;;BOOT LOAD ADDRVBINTADR DUPINIT;;INIT ADDR`$BCONT!XBCONT;;BOOT READ CONT PTjX;t%X; THE FOLLOWING BYTE?}S ARE SET BY ~%X; THE CONSOLE PROCESSOR. THEY ARE&X; ACTED UPON DURING FMS INIT ONLY.&X; THEY ARE PART OF THE BOOT RECOR@}DX; THUS DEFINING THE DEFAULTX;INITIALIZATION PARMSX;*SABYTE ;;MAX # CONCURRENT OPEN FILES3DRVBYT ;;one biA}t per drive...03 is two drives(SAFBFW ;;STORAGE ALLOCATION DIR SW/SASA ENDFMS;;STORAGE ALLOCATION START ADDRX;&B}X; THE FOLLOWING CODE READS THE FMS&X; AND CONSOLE PROCESSOR (DOS) FROMX; THE DOS.SYS FILE X;DFSFLG ;;DOS FLAGC}X;(X; 00 NO DOS FILE2X; 01 128 BYTE SECTOR DISK<'X; NOT USED! 02 256 BYTE SECTOR DISKFX;P.DFLINK =;;DOS FILE STD}ART SECTOR NUMBERZ#BLDISP };;DISPL TO SECTOR LINKd.DFLADR DFMSDH;;ADDR START OF DOS.SYS FILEnX;x XBCONT%DFSFLG;E};GET DOS FLAG!FBFAIL;;BR IF NO DOS.SYS FILEX;$ MOVESTART;;MOVE LOAD START ADDRX; QDFLINK;;GET 1ST SECTOR #F} %DFLINK%XBC1$ZBUFP;; MOVE ADDRESS TO DCB &DCBBUF $ZBUFP&DCBBUFX;, BSIO;;GO READ BOOT SECTORG} GBFAILX;"%BLDISP;;POINT TO LINK ,Q@ZBUFP7;;GET LINK HI6M>LMASK;;MASK TO LINK BITS@>;; AND SAVE LINK HIGHJ3H}T L@ZBUFP7^ FBGOODhQ@ZBUFP7;;GET LINK LOWr5;; SAVE IT|3;; AND GET LENGTH OF SECTOR Q@ZBUFP7# INCZBUFP;;GO INI}CREMENT BUF ADR7;; GET LINK LOW AGAIN?X;A;;RESTORE LINK HI!XBC1;;GO READ NEXT SECTORX; BFAILQ>;;SET FJ}OR CARRY SET;AND P,Y = $80X; BGOOD ;;SET FOR CARRY CLEART??:X;&&X; BUMP ZBUFP POINTER BY BYTE VALUE0K}X;:'DINCBPQ>;; ENTRY POINT TO ADD 128D"INCZBUFP,;; AND A-REG TO ZBUFPN OZBUFPX PZBUFPb D:INCZ1l #ZBUFPv :L}INCZ1:X;(X; MOVE START ADDRESS OF DOS.SYS FILEX; TO ZBUFP POINTERX;MOVESTARTQDFLADR PZBUFPQDFLADR}3X;SAVE #D9:FMSBSIO.M65ASECTOR I/OAX;X; BSIO - DO SECTOR I/OX; @ORG l$X;. BSIO 8X;BPDCBSEN}C;; SET SECTOR HIL'DCBSEC;;SECTOR LOVX;`&BSIORQ>DCBCRS;;ASSUME READ SECTORj%>@;;AND GET DATAtDDSIO1;;BR IF RO}EAD~X;3WRITEMODE ;; LDY# can get either 'W' or 'P'$Q>DCBCWS;;ELSE LOAD WRITE SECTOR%>;;AND PUT DATAX; P}DSIO1X; RAMDISK6;; save read/write flag$ICDNOZ;; drive number(>;; RAMDISK?H:REALDISKX;X; do RAMDQ}ISK sector I/O! X;8;; recover flag% RAMIO;; real work done elsewhere(!DSIO5;; join up for return2X;<X; end of R}RAM DISK I/OFX;P :REALDISKZ8;; just to clean up stackdX;nxX;PDCBCMD;;SET COMMAND$Q>TIMOUT;;TIMEOUT DEFAULS}T LOADEDX; DSIO2PDCBTO;;SET TIME OUT'SIOCMD;;AND SIO CMDX;Q>1;;DISK SERIAL BUS IDPDCBSBI;;SET IDXT};Q>;;SET RETRY COUNT PRETRYX;'Q>;; data length: always 128 bytesPDCBCNT;; (lower byte=128)T?;; (gets 0 U}to A reg)"PDCBCNT;; (upper byte=0),X;6X;@ DSIO4J*QSIOCMD;; $40 or $80, as saved earlierTPDCBSTA;; needed by V}SIO^ SIOV;;CALL SERIAL I/Oh IDSIO5;;IF GOOD I/O THEN RTSrX;|"RETRY;;Test: retry again?IDSIO4;; yes...loopX;W}X;%DSIO5$CURFCB;;RELOAD CURRENT FCB#C;; Y-reg has DCBSTA--SIO Status:X;@ORG l$X;. BSIO 8X;BPDCBSEU X;SAVE #D9:FMSINIT.M65AFILE MANGER ENTRY POINTAX;(X; DFMSDH - DISK FILE MANAGEMENT DISKX; HANDLER ENTRY P Y}OINTX;$ @ORG .X;8 DFMSDHB DFMOPN;;OPEN FILEL DFMCLS;;CLOSE FILEV DFMGET;;GET FILE` DFMPUT Z};;PUT BYTEj DFMSTA;;STATUSt$ DFMDDC;;DEVICE DEPENDENT CMD~X;,X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X; [}0X; This table of single bit values is used by.X; GETSECTOR and FRESECt, the allocation/X; deallocation routines. \}X;GX; This is a crazy place to put it, but we had the bytes spare here.X; BITTBL =@= = ===X; ]}-X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X;)X; and this flag, one byte below FMS's.X; initialization entry, is used ^}to disable(,X; RAMIO's wait for vertical blank before2&X; doing a sector transfer...speeds<!X; up RAMDISK I/O tremendously _}FX;P(FASTRAM ;; a negative value allowsZ;the faster transfer rate.dX;nx+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; `};;X;X; INITIALIZATION CODEX;X; @ORG  DINIT X;X; SET UP DRIVE INFOX;2X; DRVTBL - 8 BYTES-ONE a} FOR EACH POSSIBLE DRIVEX;X; 0 = NO DRIVEX; NON-ZERO = DRIVE EXISTSX;&X; DBUFA(L,H) 8 TWO BYTE ENTRYS TH b}E)X; DRIVE (VTOC) BUFFER ADR FOR A DRIVE"X;,QSASA;;MOVE START OF ALLOC6PZBUFP;;AREA TO ZBUFP@ QSASAJ PZBUFP c}TX;^QDRVBYT;;TEMP 1 IS DRIVEh"PZTEMP1;;EXCESS BITS FROM BOOTrX;|$>;;TEMP 2 ISX;3VTOCLOOPQ>;; PUT ZERO d}FOR NON-EXISTANT DRIVES"TZTEMP1;;SHIFT DR BIT TO CARRY D:DECDRV;;BR IF DR NOT THEREX; %>DVDWRQ;;SET WRITE READ OF e}F!P@ZBUFP7;;IN THE DRIVE BUFFERX;QZBUFP;;MOVE CURRENT ALLOCPDBUFAL9;;ADDR TO DBUFAQZBUFP;;AND INC ALLOC f}PDBUFAH9;;BY 144 BYTESQ>VTOCSIZE INCZBUFP;;VIA DINCBPX;*Q>DVDVTOP;; set length of regular vtoc&X;0&:DECD g}RVPDRVTBL9;; SET TABLE ENTRY:0;; DEC DRIVE NUMBERD!IVTOCLOOP;;BR IF MORE TO TESTNX;X$X; SET UP SECTOR ALLOCATION TABL h}EbX;l*X; THE SECTOR ALLOCATION TABLE (SECTBL)v$X; HAS 8 ONE BYTE ENTRIES-ONE FOR+X; EACH POSSIBLE 128 BYTE BUFFER. SABY i}TE'X; IN THE BOOT RECORD DETERMINES THE"X; NUMBER OF ENTRYS TO ALLOCATE(X; ALLOCATED ENTRIES ARE SET TO ZERO.X;)Q j}ZBUFP;; SAVE START OF SECTOR BUFFERSPSBUFSTART QZBUFPPSBUFSTARTX;)%SABYTE;; GET COUNT OF SECTOR BUFFER k}S$>X;)SECTLOOP1;; CHECK IF STILL ALLOCATING C PSECTBL9;; SET ALLOCATE BYTE .G:NEXTBUF;; SKIP BUFFER ALLOCAT } X;SAVE #D9:FMSOPEN.M65 AOPENAX;+X; DFMOPN - FILE OPEN EXECUTION ENTRY PTX; DFMOPN$ SETUP;; DO FCB SEm}T UP.! FNDCODE;;GO DECODE FILE NAME8)QICAUX19;; GET AUX1 (OPEN TYPE CODES)BPFCBOTC9;;PUT INTO FCBL$M>OPDIR;; IS THISn} LIST DIRECTORYVFOPN1;;BR IF NOT` !LISTDIR;;GOTO DIR LIST CODEjX;t#OPN1 SFDIR;;GO SEARCH FILE DIR~6X; QFCBOo}TC9;;GET OPEN TYPE CODER>OPIN;;INPUT FDFOINR>OPOUT;;OUTPUT FDFOOUTR>OPINOPOUT;;UPDATE FDFOUPDR>OPOp}UTOPAPND;;APPEND FDFOAPNERDVDC@ERROR E.DVDCX;X; DFOIN - OPEN FOR INPUT X; DFOIN 8;;GET SEARCH FLAGq}(EOPNER1;;ERROR IF NOT FOUND2 DDFOUI<X;FX; DFOUPD - OPEN FOR UPDATAPX;Z DFOUPD d8;;GET SEARCH FLAGnEOPNER1r};;BR NOT FOUNDx TSTLOCK;;TEST LOCKX; DFOUI  DFRDSU;;SET UP FOR READ!GREAT;;DONEX; OPNER1)ERFNF@Es}RROR E.FNF;; FILE NOT FOUNDX;X; DFOAPN - OPEN APPENDX; DFOAPN 8;;GET READ STATUSEOPNER1;;BR NOT FOUNt}D%CDIRD;;IF OLDQFILDIRDFDFL18;;FILE TYPE"PFCBEFLAG9;; SAVE FILE TYPE,M>DFDNLD;;THEN6FAPOER;;ERROR@ TSTLu}OCK;;TEST LOCKEDJ OPVTOC;;READ VTOCT GETSECTOR;;GET A SECTOR^$PFCBSSN9;;MOVE START SECTOR #hQFCBLSN9;;TO START v}SECTOR #r PFCBSSN9|!DHFOX2;;CONTINUE AS OPEN APOERERAPO@ERROR E.APOX;X; DFOOUT - OPEN FOR OUTPUTX; w}DFOOUT 8;;GET SEARCH FLAG EDFOX1X;! XDEL0;; delete a single file %CDIRD !OPN1AX; DFOX1 QDHOLESx};;WAS THERE A HOLEGOPNER2;;BR IF NO HOLE&/PCDIRS;;SAVE HOLE SECTOR AS CURRENT DIR SEC0& RDDIR;;GO READ CURRENT DIR SEy}CTOR:QDHOLED;;MOVE HOLE DISPL TODPCDIRD;;CUR DIR DISPLNQDHFNUM;;MOVE HOLE FNXPSFNUM;;TO CURRENTb OPVTOCl %CDz}IRDv$> Q> ?OPN1BPFILDIRDFDPFN8;;BLANK FILL FILE ENTRY FOR FILE NAME30 IOPN1BX; OPN1A  $CURFCB{}-Q>DFDINUDFDNLD;; SET FILE TYPE INTO FCBPFCBEFLAG9X; GETSECTOR;;GET A SECTOR%CDIRD;;GET DIR DISPL0PFIL|}DIRDFDSSN8;;PUT SECTOR INTO DIR REC  QFCBLSN9PFILDIRDFDSSN8 X;*2Q>DFDINUDFDOUTDFDNLD;;SET DIR ENTRY IN U}}SE4PFILDIRDFDFL18>Q>;; SET NOT LOCKEDH&PFILDIRDFDCNT8;;SET COUNT = 0RPFILDIRDFDCNT8\X;f$>p OPN2Q~}FNAME9;;MOVE FILE NAMEzR> ?;;IF WILD CARDFOPN2A;;CHANGE TO BLANK"PFILDIRDFDPFN8;;TO DIRECTORY OPN2A 32}(>  DOPN2X; WRTDIR;;GO WRITE DIRECTORY DHFOX2  SETFCB WRTN6;;FIX UP AS IF WRITEQ>FCBFAS;;SET NEW} FILE PFCBFLG9  TSTDOS;;IF NOT DOS HDHFOX3;;BR$ !WRTDOS;;ELSE DO IT. DHFOX3 8 !GREATB X;L OPNER2V -ERDFUL}L@ERROR E.DFULL;; DIRECTORY FULL` X;j X;t !X; SET UP FCB FOR FILE OPENING~ X; SETFCB Q>;;CLEAR PFCBFLG9;;FL}AG &OPNF1QSFNUM;;MOVE FILE NUM TO FCB T? T? PFCBFNO9 Q> PFCBDLN9;;DATA LENGTH PFCBCNT9;;SET CNT = 0 PF}CBCNT9 : X; X; X; SET UP FOR READ OPERATION "X; (INCLUDES "DELETE", "APPEND"( %X; AND "UPDATE" AS WELL AS "READ")}2 X;< DFRDSU SETFCB;;SET UP FCBF %%CDIRD;;MOVE START SECTOR TO LINKP QDFDFL1FILDIR8Z PFCBEFLAG9;; SAVE TYPEd M>D}FDNLD;;SET NEW SECTORn PFCBSLT9;;FLAGx QFILDIRDFDSSN8 PFCBLSN9 QFILDIRDFDSSN8 PFCBLSN9 !RDNSO;;READ} 1ST SECTORVE #D9:FMSOPEN.M65 AOPENAX;+X; DFMOPN - FILE OPEN EXECUTION ENTRY PTX; DFMOPN$ SETUP;; DO FCB SE APUT BYTEAX;X; DFMPUT - PUT A FILE BYTEX; DFMPUT PSVDBYT$ QICDNO9.PICDNOIOCBZICB8 SETUPB}0%ENTSTK;;CHK TO SEE IF ENTRY WASN'T FROM CIOL,QSTAK8;;IF HI BYTE RTS IS NOT IN OS ADDRV'R>OSBTM;;SPACE THEN A NON-CIO E}NTRY`EFRMCIO;;BR IF FROM CIOj*Q>;;ELSE PREVENT FROM DOING BURST I/Ot PICCOMZ~ FRMCIOQFCBOTC9;;IF NOT OPENM>OPO}UT;;OUTPUTFPUTER;;ERROR%FCBDLN9;;GET DATA LENGTHC RFCBMLN9;;IF SECTOR NOT FULLDPUT1;;THEN BR# WRTNXS;;EL}SE WRITE FULL SECTOREPEOF;;BR IF EOF WTBUR;;TEST BURST%>EPUT1;;BR IF NOT BURSTQ@ICBALZ7;;PUT NEXT BYTE}PSVDBYT;;AFTER BURST AREA X;PUT1#FCBDLN9;;INC DATA LENQSVDBYT;;GET DATA BYTE(%P@ZSBA7;;AND PUT IN SECTOR BUFFE}R2X;<&Q>FCBFSM;;INDICATE SECTOR MODIFIEDF LFCBFLG9P PFCBFLG9ZX;d!GREAT;;DONEnX;xPUTER!ERDVDCPEOFER}REOF@ERROR E.EOFX;ABURST I/OAX;'X; TEST BURST I/O AND DO IF POSSIBLEX;+WTBURQFCBFLG9;;IF NOT AQUIRING }SECTORSGTBURST;;NO BURST;:X;RTBURQ>;;SET READ TYPEX;"TBURSTPBURTYP;;SET BURST TYPE Q>;; SHOW NO} BURST OCCURREDPBURSTFLAGQICCOMZ;;IF CMDM>;;IS TEXT MODE"FBURSTEND;;THEN NO BURST,,HTBURLEN;; GO CHECK IF B}URST IS POSSIBLE6X;@)NXTBUR ;; LOOP FOR EACH BURST SECTORJ$TBURSTFLAG;; SHOW BURST OCCURREDTQBURTYP;; CHECK R/W FLA}G^ GWRBURhX;rX; READ BURST I/O|X;' RDNXTS;; GET NEXT SECTOR TO BUFFEREBURSTEND;; IF EOF, ABORTX;)%>;; C}OPY DATA FROM BUFFER TO MEMORY:TOMEMQ@ZSBA7 P@ZBUFP73C;; CHECK FOR END OF DATA RFCBMLN9 D:TOMEMX;- }INCZBUFP;; BUMP POINTER TO MEMORY BUFFER&!DECLENGTH;; AND GO TO LENGTH TESTX;X; WRITE BURST I/OX;&5WRBUR MOVED}ATA;; MOVE DATA FROM MEMORY TO BUFFER0" WRTNXS;; AND WRITE THE SECTOR:X;D1DECLENGTH;;; SUBTRACT FROM IOCB BUFFER LENGTH}N QICBLLZX SFCBMLN9b PICBLLZl ETBURLENv "ICBLHZ+TBURLENQICBLLZ;; TEST LOWER BYTE AGAIN"GNXTBUR;; IF LENGTH >}= 128, OKQICBLHZ;; CHECK UPPER BYTE HNXTBURX;+BURSTENDVBURSTFLAG;; CC=BURST OCCURRED:X;#X; MOVE DATA FR}OM MEMORY AREA TOX; SECTOR BUFFERX;MOVEDATA%>:MOVELOOPQ@ZBUFP7 P@ZSBA7 3C;; CHECK FOR END OF DATA  }RFCBMLN9*D:MOVELOOP4X;>)PFCBDLN9;; SET DATA LENGTH TO MAXIMUMH,!INCZBUFP;; AND INCREMENT MEMORY POINTERRX;\AG}ET BYTEAfX;pX;zX; DFMGET - GET A FILE BYTEX; DFMGET  SETUP;;GO SET UPQFCBOTC9;;IF OPEN FORM>OPDIR;;D}IR CNT FGET1!GDCHAR;;THEN GO TO DIR RTNX;GET1QFCBDLN9;;GET DATA LENRFCBMLN9;;TEST EMPTY SECTORDGET2;;B}R IF NOT EMPTY RTBUR;;DO BURST IF POSSIBLE RDNXTS;;GET NEXT SECTOR DGET1;;BR IF NOT EOF !ERREOF;;ELSE EOF ERROR}$ X;. GET2?8 Q@ZSBA7;;GET DATA BYTEB PSVDBYT;;SAVE THE BYTEL 3V C` PFCBDLN9;;AND SET NEW VALUEt %FCBLSN9;;DO EOF} LOOK AHEAD~ HGET3;;IF LSN NOT ZERO %FCBLSN9;;THEN HGET3;;NOT EOF &RFCBMLN9;;IF LSN=0 THEN CHECK FOR DGET3;;}LAST BYTE Q>;;IF LAST BYTE THEN RTS !RETURN X; GET3!GREAT PSVDBYT$ QICDNO9.PICDNOIOCBZICB8 SETUPBFX;SAVE #D9:FMSCLOSE.M65 ACLOSEAX;X; DFMCLOSE - CLOSE A FILEX; DFMCLS$ SETUP.QFCBOTC9;;GET OPEN C}ODE8M>OPOUT;;IF NOT OUTPUTBFCLDONE;;THEN DONELX;V&UFCBFLG9;;IF NOT ACQUIRING SECTORS`DCLUPDT;;THEN IS UPDATEjX};t WRTLSEC;;WRITE LAST SECTOR~X; RRDIR;;GO GET DIRECTORY#QFCBCNT9;;GET CNT OF SECTORS5 QFCBCNT95X;}QFCBOTC9;;GET OPEN CODEM>OPAPND;;IF NOT APPENDFCLOUT;;BRX;QFCBEFLAG9;; SAVE FILE TYPE5! DFRDSU;;ELSE} SET UP FOR READ 7;; AND RESTORE ITPFCBEFLAG9X;(APP1 RDNXTS;;READ TO EOF2 DAPP1<X;FQFCBSSN9;;MOVE START S}ECTORPPFCBLSN9;TO EOF LINK SECTORZQFCBSSN9dPFCBLSN9n! WRTN2;;THEN WRITE AS NOT EOFxX;CLOUT%CDIRD;;GET} DIR DISPL,7OFILDIRDFDCNT8PFILDIRDFDCNT87OFILDIRDFDCNT8PFILDIRDFDCNT8X;'QFCBEFLA}G9;; GET FILE TYPE FROM FCBPFILDIRDFDFL18 WRTDIR;;WRITE DIR WRTVTOC;;WRITE VTOCX;CLDONEQ>;;CLEAR OPEN }CODE PFCBOTC9" !FGREAT,X;6 CLUPDT @$UFCBFLG9;;IF SECTOR NOT MODIFIEDJDCLDONE;;THEN DONET WRCSIO;;ELSE WRITE} IT^!CLDONE;; THEN DONEhX;r|X;X; RE-READ DIR RECORDX; RRDIR QFCBFNO9;;GET FILE NUMBERV?V? PS}FNUMX;X; FNSHFT;;SET ACU=FILE NO/64PCDIRS;;TO GET DIR SECTOR FNSHFT;;SET ACU TO REM=16 FNSHF1T?P}CDIRD;;TO GET DIR DISPLX;& !RDDIR0FNSHFTQ>:FNSHF1%>;;SHIFT 3 BITS OFD%FNSHF2TFCBFNO9;;FILE NO INTO ACUNU?}X1b HFNSHF2l:MSCLOSE.M65 ACLOSEAX;X; DFMCLOSE - CLOSE A FILEX; DFMCLS$ SETUP.QFCBOTC9;;GET OPEN CION IF DONE* DINCBP4:NEXTBUF2;; INC BUF#>(>;; ALL 8 DONE?H HSECTLOOPRX;\X; SET LOW MEMfX;pQZBUFP;;MOVE F}X;SAVE #D9:FMSXIO.M65 ARENAMEAX;%X;XRENAME - RENAME A FILE OR FILESX; XRENAME$ FNDCODE;; get past ol}d name.# FNDCNX;; get new name to FNAME8X;B$> ;; 11 character nameL :SVFNLPV QFNAME9`PNEWNAME9;; save new namej}0tI:SVFNLP;; all of it~X;X;,X; new name in NENAME, get old name againX; and ensure it exists! NEEDFILE};; does all that!X;/X; found at least one match on old file nameX; :RNMLP$ TSTLOCK;; abort if file locked!( }TSTDOS;; ask: is this file DOS.SYS?#6;; save answer to that questionX;$X; here we do the actual renaming X;$>;;} beginning of name&WILDFLAG;; initialize flag('%CDIRD;; offset in directory sector2X;< :CHARLPF)QFNAME9;; char fr}om as-given old namePR> ?;; wild card?ZH:NOTWILD;; nod""WILDFLAG;; yes...set the flagn/RNEWNAME9;; also wild in as-g}iven new name?x!H:ERFNM;; no! illegal rename!X; :NOTWILD+QNEWNAME9;; a char of as-given new nameR> ?;; wild?}F:WILD;; yes0PFILDIRDFDPFN8;; store a char of new name! :WILD3;; next char in dir sector2;; next char in NEWNA}ME$(> ;; 11 chars in file name yet?H:CHARLP;; nopeX;-X; okay...we managed to do a valid rename!X;&8;; but wa}s the old name "DOS.SYS"?H:NDOS1;; no"' DELDOS;; yes...change boot sectors,X;6 :NDOS1@& TSTDOS;; what about the n}ew name?J+H:NDOS2;; not "DOS.SYS"...okay to go onTX;^X; new name is "DOS.SYS"hX;r'$CDIRD;; offset in directory sect}or|,QFILDIRDFDSSN9;; msb: start of file#%FILDIRDFDSSN9;; lsb: ditto! SETDSO;; change boot sectorsX; :N}DOS2$ WRTDIR;; write directory sectorX;+QWILDFLAG;; any wild cards in old name?F:RNMRTS;; noX;+ CSFDIR;; s}earch for next matching name&D:RNMLP;; found another...continueX;X; no more names to renameX; :RNMRTS&!FGRE}AT;; we don't need the buffer&X;0 :ERFNM:!ERFNAME;; bad file nameD ADELETEANX;X/X; XDELETE - DELETE ALL FILENAME}S THAT MATCHbX;l XDELETEv- NEEDFILE;; decode name, ensure it exists XDELX  XDEL0 TSTDOS HXDELY DELDO}S XDELYX; WRTDIR;;WRITE DIR ENTRY CSFDIR;;LOOK FOR NEXT MATCHDXDELX;;BR IF FOUND WRTVTOC !FGREATX};$X; to delete a file, we must read #X; all its sectors, deallocating)X; them from the VTOC bit map as we go X;*XDE}L0 OPVTOC4X;>XDEL1%CDIRD;;GET DIR DISPLH TSTLOCK;;GO TEST LOCKRQ>DFDEDE;;LOAD DELETED FLAG\!PFILDIRDFDFL18;;}DELETE FILEfX;p DFRDSUz#:XDEL2 FRESECT;; FREE A SECTOR* RDNXTS;; GET THE NEXT ONE INTO BUFFER*D:XDEL2;; AND REP}EAT UNTIL END-OF-FILEX; XDEL4 !%>DVDWRQ;;TURN ON WRITE REQ'D*C;; BY PUTTING NON-ZERO VALUE INTO VTOCP@VTOCPTR}7 :XDLRT:X;ALOCK AND UNLOCKAX;X; XLOCK - LOCK A FILE X; XUNLOCK - UNLOCK A FILE X; XLOCK$ Q>DFDL}OC;; SET LOCK. @SKIP2 ;; (skips to XLCOM)8 XUNLOCKB Q>;;SET UNLOCKL XLCOM ;; common code!V PTEMP4` X;j . NEEDF}ILE;; decode name & ensure it existst X;~ "XLC1%CDIRD;;GET CURRENT DISPL #QFILDIRDFDFL18;;GET LOCK BYTE M>;;TURN O}FF LOCK LTEMP4;;OR IN LOCK/UNLOCK 'PFILDIRDFDFL18;;SET NEW LOCK BYTE  WRTDIR;;GO WRITE X; CSFDIR;;LOOK FOR NE}XT MATCH DXLC1;;BR FOUND !FGREAT;;ELSE DONE X; ;X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; !X; T}STLOCK - TEST FILE LOCKED X; TSTLOCK %CDIRD;;GET DIR DISPL( $QFILDIRDFDFL18;;LOAD LOCK BYTE2 M>DFDLOC;;MASK LOC}K BIT< (F:XDLRT;; not locked...normal returnF ;(fall thru to error)P X;Z TLFd ERFLOCK@ERROR E.FLOCKn APOINTAx }X; X; XPOINT - POINT REQUEST X; XPOINT QFCBFLG9;;IF ARQ SECTORS GPERR1;;POINT INVALID QICAUX49;;IF REQUEST IS} NOT RFCBCSN9;;SAME AS CURRENT HXP1;;THEN BR QICAUX39 RFCBCSN9 FXP2;;ELSE NO NEED TO CHANGE X; !XP1QFC}BFLG9;;IF NOT MODIFIED FXP1A;;BR  WRCSIO;;ELSE WRITE IT Q>" PFCBFLG9, XP1A 6 QICAUX49@ PFCBLSN9J QICA}UX39T PFCBLSN9^  RDNSO;;READ REQ SECTORh EXPERRr X;| #XP2QICAUX59;;TEST REQ DATA LEN RFCBMLN9;;LESS THEN MAX D}XP3 FXP3 XPERR ,ERRPDL@ERROR E.PDL;;IF NOT THEN ERROR X; "XP3PFCBDLN9;;SET NEW DATA LEN !GREAT X; P}ERR1 ERRPOT@ERROR E.POT ANOTEA X; "X; XNOTE - EXECUTE NOTE REQUEST X; XNOTE& QFCBDLN9;;DATA LENGHT VALUE0} PICAUX59;;TO AUX 2: QFCBCSN9;;CUR SEC NO (LO)D PICAUX39;;TO AUX 3N QFCBCSN9;;CUR SEC NO (HI)X PICAUX49;;TO AUX  } X;SAVE #D9:FMSALLOC.M65AFREE SECTORAX;#X; FRESECT - FREE CURRENT SECTORX; FRESECT$'QFCBCSN9;; get ls8}b of sector number."5;; save for just a tick or two8)M>;; use 3 least significant bits...B?;; ...as an indexL7;; get 8}FCBCSN,X backV,LFCBCSN9;; check out complete sec num`%F:FRRTS;; can't free sector zero!jX;t/X; okay...real sector a8}nd Y-reg has index...~#X; ...into single bit mask tableX;"QBITTBL8;; so get a single bit#5;; save mask until ready f8}or itX;QFCBCSN9;; get lsb again#%>;; shifting right 3 times.../:FRE1VFCBCSN9;; will divide sector #...$W?8};; ...by 8, making a byte index1 H:FRE1X;,.O>DVDSMP;; offset to start of vtoc bit map ?;; ...true index...8}"7;; (recover proper bit number)L@VTOCPTR7;; set bit..(,P@VTOCPTR7;; ...meaning sector available2X;<2X; now we must 8}increment one of the sector cntsFX;PX; which one?ZX;d))>DVDVTOP;; past top of regular vtoc?n"%>DVDNSA;; assume regu9}X;SAVE #D9:FMSFMT.M65ADEVICE DEPENDENT COMMANDAX;-X; DFMDDC - DEVICE DEPENDENT CMD EXECUTIONX; DFMDDC$ } SETUP;;SET UP FOR EXECUTION.QICCOM9;;GET COMMAND8R>;;is it regular format?B%F:FMT1;;yes...go try for MFM modeL' }R>;;what about forced density fmt?VF:FMT2;;yes...do it`X;jX; not a format request...t&X; ...try for one of the st }andard~X; FMS capabilities.X;R>MAXDDC;;TEST RANGEEDVDCER;;BR OUT OF RANGE;S> ;;SUBTRACT BASE OF CMDS }DDVDCER;;BR OUT OF RANGET?? QDVDCVT85;;PUSH EXECUTION ADDRQDVDCVT85: X; DVDCVT XRENAME };; $20-RENAME( XDELETE;; $21-DELETE2 DVDCER;; $INVALID CMD< XLOCK;; $23-LOCKF XUNLOCK;; $24 }-UNLOCKP XPOINT;; $25-POINTZ XNOTE;; $26-NOTEdX;nMAXDDC';;MAX DVDC+1xX;DVDCER!ERDVDCX;A } FORMAT DISKETTEAX;X; the format tables:1X; each table gives (1) number of vtoc bytes2X; for a given }drive type, and (2) firstX; five bytes of vtocX; TYPETBL TYPE810 DVDVTOP;; 720 sectors ;; dos typ }e3  = ;; max sectors, current sector cntX; TYPE1050" DVDETOP;; 1024 sectors, ;; dos type63 = } ;; max sectors, current sector cnt@X;J TYPERAMT DVDRTOP;; 512 sectors^ ;; dos typeh3  = ;; max sec }tors, current sector cntrX;|X;!X; XFORMAT - FORMAT A DISKETTEX;!:FMT2 ;; New XIO 253 command(QICAUX19;; d }id user specify density?H:FMT2A;; yes)Q>DCBCFD;; no...assume single density :FMT2A$>;; used as flag F:FMTJN }X;X;%:FMT1 ;; Original XIO 254 format$Q>DCBCFMFM;; start with MFM mode!>;; any non-zero value is flagX; fal }l thru&X;0 :FMTJN:*&WILDFLAG;; otherwise used only by REND XFORMATN+PDCBCMD;; set up for use by XIO vectorsX!QICD }NOZ;; what device number?b2$>TYPERAMTYPETBL;; loc'n of RAMDISK size tbllR>;; ram disk?vF:NOSIO;; yes...no SIO call }X;"QVTOCPTR;;MOVE VTOC BUF ADRPDCBBUF;;TO DCB QVTOCPTR PDCBBUF %>@;;TELL SIO RECIEVING DATA&QDSKT }IM;;GET FORMAT TIME OUT VALUE, DSIO2;;GOTO LOCAL DISK HANDLER THEN SIOX;*I:FMTSIZE;;IF NO ERRORS CONT FORMATING*X; } got an error from SIO format request)>E.NAK;; bad request?&H:OOPS;; no...has to be real error($WILDFLAG;; was this } XIO 254 or 253? FXFERR;; 253...no retryX; 0Q>DCBCFD;; yes...what kind of format was it?*RDCBCMD;; standard FM typ }e?4$HXFORMAT;; no...so try that now!>'X; either tried both types of formatH)X; or got error on single density typeR XFE }RR\!RETURN;; quit with errorfX;p*X; if here, got an error other than NAKzX; :OOPS&)>;;ELSE CK FOR DEVICE DONE }ERRORHXFERR;;NO, THEN ERROR EXITX;(X; if DEVICE DONE error, there can be)X; several causes (no disk, door open,) }X; write protect set, etc.), so we see'X; if reason for DEVICE DONE was bad"X; sectors found in formatting.X;!;ELSE } CHK FOR BAD SECTOR INFO%>;;RETURNED BY CONTROLLER"Q>;; drive uses $FFFF to mark ;end of bad sector list in #;d }ata returned from format call R@VTOCPTR7;; is list empty?$ /HXFBAD;;no...so there were some bad sectors. 38 +R@VTOCPTR7 };;still trying for list emptyB $FXFERR;;aha! list is empty...soL 2XFBAD ;; ...DEVICE DONE is for another reasonV @ERRO }R E.DBAD;; sigh.` X;j 1X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;t X;~ *X; format was ok...how big is the disk? X; } :FMTSIZE .$>TYPE810TYPETBL;; assume single density "QDCBCMD;; which format worked? R>DCBCFD;; single density? !F }:NOSIO;; yes...tbl ptr in X! 1$>TYPE1050TYPETBL;; no...assume MFM density X; *X; when here, X-reg is offset to proper } X; VTOC set-up table... X; :NOSIO %X; first, we zero all of vtoc area Q> +%>DVD2.5;; max size of extended vt }oc :ZLPP@VTOCPTR7( 12 H:ZLP< *X; we didn't change byte 0 of the vtoc,F (X; but that's okay becuz the tableP &X; }changes first 5 bytes anyway!Z X;d X; when here, Y-reg is zeron #X; X-reg pts to a tblx X; %QTYPETBL9;; first } byte from table 'PMAXVTOC;; is top of pertinent VTOC X; X; :VTSLP 2;; to next byte of tbl $QTYPETBL9;; a byte f"B} X;SAVE #D9:FMSDIR.M65ALIST DIRECTORYAX;"X; LISTDIR - LIST THE DIRECTORY%X; GDCHAR - GET NEXT DIR CHARACTER$}&X; THE DIRECTORY IS LISTED VIA OPEN$&X; LIST DIRECTORY FUNCTION EACH DIR.&X; ENTRY THAT MATCHES THE FILE SPEC8(X; IS CO$}NVERTED TO A PRINTABLE FORMATB)X; INTO A SECTOR BUFFER. THE GET BYTEL(X; ENTRY IS USED TO GET THE PRINTABLEV$X; CHARACTER$}S ONE AT A TIME. THE`#X; LAST LINE PRINTED IS ALWAYS Aj+X; COUNT OF THE NUMBET OF SECTORS IN USEt0X; AND THE NUMBER REMAI%}NING AVAILABLE SECTORS~X; LISTDIR" SFDIR;; Search for first name+D:LDJN;; found a name...join with FDENTX;'X;%} no more name matches in directoryX; :LDFREE" RDVTOC;; ensure VTOC in place %>DVDAUX*Q@VTOCPTR7;; get LSB of a%}ux sector cnt %>DVDNSA,-O@VTOCPTR7;; add in LSB or std sector cnt 5;; save for a nonce3+Q@VTOCPTR7;; MSB of %}standard sector cnt(%>DVDAUX2+O@VTOCPTR7;; is added to MSB of aux cnt<>;; we need this in A-reg...F7;; ...but thi%}s..P?;; ...has to be in Y-regZ!A;; so now it is back in A-regdX;n&X; free sector cnt in Y,A (lsb,msb)xX;$>0&D%}IRCPTR;; so that cnt is at start of buffer% CVDX;; convert to decimal number%>;; right after count...A$P@ZSBA7;%}; put space or plus sign3;; to start of msgX; add FREE SECTORS message :FRMSGLP2Q:FSMSG8;; becuz Y starts at 4%} in this loopP@ZSBA7;; a byte of msg3)>;; at end ?H:FRMSGLP;; no- :CVEOL;; add RETURN and set DIRCPTR to 0%}:GREATEXIT""!GREAT;; exit with good status,#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6X;@!X; This entry point is used byJ X% }; the FMS get-a-byte routineT"X; when it discovers that input^#X; is occurring from a file openhX; in DIRECTORY mode.rX% };|#X; Here, we simply pass back the#X; formatted entry one byte at a'X; time until an entry is exhausted.(X; Then we g% }o format another line, ifX; there is more to do.X; GDCHAR#%DIRCPTR;; get and test pointer I:GDOK$!ERREOF;; % }no more char's to get!X; :GDOKQ@ZSBA7;;GET NEXT CHARPSVDBYT;; IN SVDBYT#DIRCPTR;;INC COUNTR>EOL;;TEST I% }F EOL DONEH:GREATEXIT;;BR NOT EOL&)>;;WAS THIS AN ENTRY0ELDENT;;BR IF IT WAS:Q>;;ELSE INDICATE ENDDPDIRCPTR%};;IN DIRCPTRN-!FGREAT;;DONE...release the sector bufferXX;b3X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lX;v1X; L%}DENT is used to get another file name line(X; formatted into the sector bufferX; LDENT " CSFDIR;;SEARCH FOR NEX%}T MATCH,E:LDFREE;;NO MORE MATCHES, give free cnt :LDJN FDENT;;FORMAT ENTRY!GREAT;;DONEX;X;-X;;;;;;;;;;;%};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X; :FSMSG AFREE SECTORSA X; X;*+X; FORMAT DIR ENTRY INTO A SECTOR BUFFER4X%};> FDENTH$CDIRD;; current dir entryR%>;;START AT DISPL ZERO\Q> ;;START WITH A BLANKf P@ZSBA7;;formatted in buff%}erpQFILDIRDFDFL19z M>DFDLOC;;BUT IF FILE LOCKED F:LD1Q> *;;CHANGE TO ASTERISK P@ZSBA7:LD13Q> ;;FOL%}LOWED BY A BLANK P@ZSBA73X;0X; now move the name from directory to bufferX;*LD2QFILDIRDFDPFN9;;MOVE THE 1%}1 CHARP@ZSBA7;;FILE NAME 2 3 )> $ DLD2. X;8 Q> ;;FOLLOWED BY A BLANKB P@ZSBA7L 3V )'DIRCPTR;; where we wa%}nt # of sectors` X;j X;t %X; now we check to see if extended~ %X; file type needs to be indicated X; ($CDIRD;; back to %}look at current dir QICAX1Z;; what kind of open? W?;; (mode 6 or mode 7?) D:LD3;; mode 6...do nothing X; indicate w%}hether extended QFILDIRDFDFL19;; file type #W?;; extended file is $03 or $23 !D:LD3;; not extended...ignore &1;; bac%}k to where we just put space Q> > 'P@ZSBA7;; form becomes "" %>;; right after asterisk Q> < %P@ZSBA7;; %}other half of indicator X;( :LD32 X;< X; ready for cnt of sectorsF X;P X;Z %FILDIRDFDCNT9;;SET A,Yd &QFILDIRDF%}DCNT9;;=SECTOR COUNTn X;x CVDX $>d;;CONVERT AND MOVE  CVDIGIT;;100S DIGIT $>  CVDIGIT;;10S DIGIT $> %} CVDIGIT;;1S DIGIT X; )X; but this routine gives a max number 'X; of 999...and free sector cnt gets #X; a plus sign if %}cnt is greater X; $> ;; assume a space C;; remainder !F:LT1000;; less than 1000, ok +$> +;; greater than 999...need%} plus sign :LT1000" X;, %>;; where we want the EOL6 X;@ ,X; put out an EOL and reset entry pointerJ X;T :CVEOL^ Q%}>EOL;;AND EOLh P@ZSBA7r %>| 'DIRCPTR;;SET CHAR CNT = 0 : X; -X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; (X% }; CVDIGIT -- routine puts next digit X; of number into entry X; CVDIGIT &TEMP3;;SAVE DIGIT VALUE $> X; %!}:CVD1 PZTEMP2;;SAVE CURR VALUE HI 'ZTEMP1;;AND LOW 2;; INC DIGIT COUNTER ;;;SUBRTACT DIGIT VALUE& QZTEMP1;;FROM %"}CUR VALUE0 STEMP3: ?D QZTEMP2N S>X -D:CVD2;; went minus...we went one too farb X;l "(> ;; got max digit value yet?%#}v H:CVD1;; no ;yes...fall through! X; :CVD2 X; A;;DIGIT TO ACU L>0;;PLUS ASCII ZERO %DIRCPTR;;GET OUTPUT %$}INDEX P@ZSBA7;;AND SET DIGIT #DIRCPTR;; INC OUTPUT INDEX *QZTEMP2;;LOAD VALUE HI (for next call) %ZTEMP1;;AND VALU& }H X;SAVE #D9:FMSFNAME.M65AFILE NAME DECODEAX;"X; FNDCODE - DECODE A FILE NAMEX;(X; THE USER FILENAME IS P)&}OINTED TO BY$+X; ICBALZ, IT IS ON THE FORM P X WHERE P.-X; IS THE PRIMARY FILE NAME (1 TO 8 CHARS)8%X; AND X IS THE EXTEND)'}ED FILE NAMEB-X; (0 TO 3 CHARS). THE PERIOD IS OPTIONALL*X; (IF NOT PRESENT, THEN NO EXTENSION).V+X; THE DECODED FILENAME)(} WILL BE 12 CHARS`&X; IN LENGTH. THE P FIELD WILL BE j(X; LEFT JUSTIFIED IN THE 1ST 8 BYTES.t+X; THE X FIELD WILL BE LEFT))} JUSTIFIED IN~(X; THE LAST 3 BYTES. BLANKS ARE USED%X; TO PAD THE FIELDS TO FULL SIZE.)X; IF THE USER SPECIFIED P OR X )*}FILEDS.X; CONTAIN MORE THAN 8 OR 3 CHARS, THEN THE'X; EXTRA CHARS ARE IGNORED. THE '*'(X; WILD CARD CHAR WILL CAUSE TH)+}E REST&X; OF THE FIELDS TO FILLED WITH THE/X; '?' WILD CARD CHAR. ANY NON-ALPHANUMERIC#X; CHAR TERMINATES THE FILENAME),}.X; FNDCODE$%>;;find beginning of real name:FDCLPQ@ICBALZ71 $G:FNERR;;we only allow D: or Dn:R> : H)-}:FDCLP(3;; POINT PAST THE COLON2X;<X; secondary entry point:F1X; Y points one byte before name to decodePX;Z F).}NDCNXd 3;; to real beginning of namen"Q>;; max chars in name properxX;$>;; destination indexX; :FDLPSPCL-P)/}EXTSW;; save end of current portion here:FDMAINLOOPQ@ICBALZ7;; get a characterR> .;; start extension?H:FDNP;;)0} noX; found a period:!(>;; at end of primary name?6H:FDPERIOD;;not exactly in right place, space fillX;3X; got)1} a period & we have space filled if needed*X; ....time to switch over to extensionX;%3;; now we can get past the perio)2}d"!Q> ;; and switch to extension,&H:FDLPSPCL;; special loop re-entry6X;@ :FDPERIODJ-D:FDSPACE;; in main name, space)3} fill onlyT)X; otherwise, treat period as bad char^-X; ...so fall thru to discover it is 'bad'hX;r :FDNP|!R> *;; rest )4}of this part wild?H:FDNSTAR;; no+Q> ?;; yes...fill with single wild cards$(EXTSW;; at end of this portion?#E:FDOK)5};; force Y off of the '*'D:FDFILL;; just fillX;2X; if here, not one of the repeating charactersX; :FDNSTARR)6}> ?;; the wild card?F:FDOK;; yesR> 0;; a numeric?)D:FDBAD;; no...bad char...end of name&R> 9;; maybe...numeric)7} chk againD:FDOK;; yes...'0 to '9)M>;; not numeric...change lower case&R> A;; alpha?0D:FDBAD;; nope...kablooey:)8}$R> Z;; maybe...try alpha againDD:FDOK;; yep...A to ZNX;X%X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;bX;l(X; if bad charac)9}ter, fill with spacesvX; :FDBAD)Q> ;; ensure we go all the way to end PEXTSW#(> ;; is this bad char after...)):}F:FDEXIT;; we already have full name?';if here, no...need to keep fillingX; :FDSPACEQ> ;; space fill H:FDFIL);}LX;/X; if here, is legitimate filename characterX; :FDOK 3;; so bump to next charX; 'X; now, put char in FNA)<}ME, if proper*X;4 :FDFILL>$(EXTSW;; at end of this portion?H0F:FDMAINLOOP;; yes...don't put char in FNAMER)PFNAME9;)=}; no...finally, a legit char!\2;; to next characterfX;p"H:FDMAINLOOP;; and do it againzX;-X; have now stored 11 cha)>}racters in FNAME!X; :FDEXIT%QFNAME;; what is first character?R> ;; a space?F:FNERR;; yes#$CURFCB;; can ne)?}ver forget this:;; no...name is decodedX;X;&X; oops...no characters in filenameX; ERFNAME :FNERR !@ERR*}. X;SAVE #D9:FMSSRCH.M65ADIRECTORY SEARCHAX;#X; SFDIR - SEARCH FILE DIRECTORY$X; CSFDIR - FILE DIRECTORY SEA-A}RCHX;$,X; THE FILE DIRECTORY IS SEARCHED FOR THE.+X; FILENAME IN FNAME. THE SEARCH STARTS8/X; AT THE CENTRAL SECTOR+1 -B}AND WILL CONTINUEB+X; FOR UP TO A TOTAL OF 8 SECTORS. WHENL(X; TESTING FOR FNAME MATCH, '?' FNAMEV.X; CHARS WILL ALWAYS M-C}ATCH THE CORESPONDING`-X; DIR FILENAME CHAR. IF A MATCH IS FOUNDj2X; CDIRS CONTAINS THE RELATIVE DIRECTORY SECTORt,X; NUM-D}BER (0-7) AND CDIRD (AND THE Y REG)~-X; CONTAINS THE DISPLACEMENT OF THE ENTRY.5X; AFTER A MATCH HAS BEEN FOUND, THE DIREC-E}TORY CAN2X; BE SEARCHED FOR ANOTHER MATCH VIA THE CSFDIR1X; ENTRY POINT. IF A MATCH HAS NOT BEEN FOUND-X; THEN DHOLES -F}AND DHOLED WILL POINT TO A &X; DIRECTORY HOLE THAT CAN BE USED.0X; IF DHOLED = FF THEN THE DIRECTORY IS FULL.0X; THE CA-G}RRY IS RETURNED CLEAR IF FILE FOUND,X; SET IF FILE NOT FOUND.X; SFDIRQ>;;INIT TO -1PDHOLES;;DIR HOLE SECTOR-H}PCDIRS;;CUR DIR SECTOR PSFNUM;;FILE NUMBER$Q>p;;INIT TO -16 (-ENTRY LENGTH)PCDIRD;;CUR DIR DISPL(X;2 CSFDIR-I}< #SFNUMF,P!QCDIRD;;CDIRD=CDIRD+ENTRY LENZ O>DFDELNd!ISFD2;;IF RESULT <128 THEN BRnX; ELSE AT END OF DIR SECTx"#-J}CDIRS;;INC TO NEXT DIR SECTORQ>;;TEST END OF DIR RCDIRSDSFD1;;BR NOT END FSDRTNX;)SFD1 RDDIR;;READ THE-K} NEXT DIR RECORDQ>;;SET DIR DISPL = 0X;"SFD2PCDIRD;;SET NEW DIR DISPL?;;PUT DISPL IN Y AS INDEXX; QFILDI-L}RDFDFL18;;GET FLAG 1.FSFDSH;;BR IF UNUSED (END OF USED ENTRIES)GSFDSH;;BR IF DELETED&M>DFDEXTDFDINU;; mask for -M}safety$R>DFDEXT;; BR IF "EXTENDED" FILE" F:INUSE,M>DFDOUT;;IF OPEN OUTPUT6HCSFDIR;;DON'T FIND IT@X;J"X; ENTRY I-N}N USE, TEST FOR MATCHT&:INUSE$>;;TEST MATCH ON 11 CHARS^ SFD3QFNAME9;;FILE NAME CHARhR> ?;;IS FNC WILD CARDrFSFD4-O};;THEN IT MATCHES|1RFILDIRDFDPFN8;;ELSE IT MUST MATCH FOR REAC'HCSFDIR;;IF NOT MATCH THEN TRY NEXTSFD42;;INC CHAR -P}CNT3(> ;;TEST ALLHSFD3;;AND CONTINUE CHECKX;,;;WE HAVE A MATCH DSDRTNX; SFDSH QDHOLES;;IF DHOLES-Q} NOT MINUS*ISFDSH1;;THEN ALREADY HAVE A GOOD HOLEX; X; ELSEX;"QCDIRS;;MOVE CURR DISPL SECTOR&"PDHOLES;;AND CU-R}RRENT DIR DISPL0$QCDIRD;;TO HOLE SECTOR AND DISPL: PDHOLEDDQSFNUM;;SAVE HOLENPDHFNUM;;FILE NUMBERXX;b2SFDSH1QF-S}ILDIRDFDFL18;;IF HOLE WAS A DELETEDl GCSFDIR;;ENTRY THEN CONTINUEvX;X; ELSE WE ARE AT END OFX;&;;;USED ENTRIES -T}THUS FILE NOT FOUND SDRTN$CURFCB;;RESTORE X REG:X;!X; routine to do three things:X; 1. decode file name'X;-U} 2. search for file in directory0X; 3. abort with file name error if not fndX; NEEDFILE FNDCODE;; what's the -V}name? NEEDSRCH  SFDIR;; search for itE:NEEDBAD;; oops :*X;4 :NEEDBAD>!ERFNF;; file not foundHX;CTORY SEA,tX;SAVE #D9:FMSRWSEC.M65AWRITE DATA SECTORAX; X; WRTNXS - WRITE NEXT SECTORX; WRTNXS$"QFCBFLG9;;IF AC1X}QUIRING SECTORS.GWRTN1;;THEN NOT UPDATE8X;BT?;;IF SECTOR NOT MODIFIEDLIWRU1;;THEN DON'T ITVX;`T?j PFCBFLG9;;T1Y}URN OFF FLAG BITSt! WRCSIO;;WRITE CURRENT SECTOR~GWRNERR;;BR IF BAD I/O'WRU1!RDNXTS;;ELSE READ NEXT SECTORX;&W1Z}RTN1 GETSECTOR;;GET A NEW SECTORX;"WRTLSECQFCBDLN9;;GET DATA LEN%>DRVLBT;;INTO LAST BYTEP@ZSBA7;;OF SECTOR1[}X;'WRTN2QFCBLSN9;;MOVE LINK SECTORLFCBFNO9;;PLUS FILE NUM%>DRVMDL;;TO BYTES 126,127P@ZSBA7;;OF SECTOR BUFF1\}3  QFCBLSN9 P@ZSBA7X;( WRCSIO;;WRITE SECTOR2IWRTN5;;BR NOT ERROR<X;F WRNERRPQ>;;CLOSE FILEZ PFCBOT1]}C9dQDCBSTA;;RECOVER ERROR CODEn !RETURNxX; WRTN5#FCBCNT9;;INC SECTOR CNT HWRTN6#FCBCNT9 WRTN6 1^}MVLSN;;LINK TO CURQ>PFCBLSN9;;LINK = 0PFCBLSN9PFCBDLN9;;DLN = 0 Q>DRVMDL PFCBMLN9,:X;W1_}RCSIO;;;WRITE CUR SECTOR"RWCSIOQFCBCSN9, %FCBCSN96 !DSIO@X;JMVLSNQFCBLSN9;;MOVE LINKT PFCBCSN9^QFCBLSN1`}9hPFCBCSN9r:|X;AREAD DATA SECTORAX;X; RDNXTS - READ NEXT SECTORX; RDNXTSQFCBFLG9;;IF NOT UPD1a} MODEFRDNSO;;BR!WRTNXS;;ELSE WRITE FIRST RDNSO QFCBLSN9;;IF LSN NOTLFCBLSN9;;ZEROHRDNS1;;BR;;;E1b}LSE EOF:&RDNS1 MVLSN;;MOVE LINK TO CURRENT ,;;READ& RWCSIO;;CURRENT SECTOR0GRDIOER;;BR IF OK READ:X;DX; EL1c}SE GOTO I/O ERRORNX;X %>DRVMDLbQ@ZSBA7;;TEST FOR SAMElM>;;FILE NOv RFCBFNO9HRDFNMM;;IF NOT THEN ERRORX;1d}Q@ZSBA7;;MOVE LINK SECTORM>PFCBLSN93 Q@ZSBA7 PFCBLSN9X;3;;INC TO LEN BYTEQ@ZSBA7;;GET LEN BY1e}TE 5;;SAVE IT!QFCBSLT9;;GET SECTOR LEN TYPEHRDNS3;;BR IF NEW TYPE X; 7;;GET LEN "GRDNS2;;BR IF OLD SHORT SECTO1f}R*Q>};;ELSE SET FULL SECTOR4RDNS2M>;;TURN OFF MSB>5;;BALANCE STACKHX;R RDNS37\PFCBMLN9;;SET MAX LENfX;pQ1g}>;;SET CUR DATA LEN = 0z PFCBDLN9,:RDIOER ERRIO;;I/O ERROR"RDFNMM ;;FILE NUMBER MISMATCH QICCOM9R>!1q}b;FMSEQU M65b<FMSBOOT M65b MFMSBSIO M65bXFMSINIT M65blFMSOPEN M65bFMSBYTE M65b FMSCLOSEM65b%FMSXIO M65b-FMSFMT M65b*FMSDIR M65b%FMSFNAMEM65b@FMSSRCH M65bWFMSRWSECM65b"rFMSVTOC M65bFMSALLOCM65b FMSSETUPM65bFMSDOS M65bFMSEXIT M65b$FMSRAM M65b FMS M65bFMSSTAT M65b FMSTEST M65b)"FMS REFbFMSBANK M65bFMSRAMIOM65bXFMSEND M65bB^BUG4000 COMb#FMS OBJFMS OBJ;;WAS THIS DELETEFRDDELE;;BR IF DELETEERFNMM@ERROR E.FNMM#RDDELE;;;INDICATE EOF TO DELETE:X;CBFLG9;;IF AC0pTX;SAVE #D9:FMSVTOC.M65AREAD/WRITE DIRAX;&X; RDDIR/WRDIR READ/WRITE DIRECTORYX;$ RDDIR.,;;SET READ5s}8 DDIRIOBX;L WRTDIRV;;;SET WRITE`X;j DIRIOt6;;SAVE READ WRITE~X;,QCDIRS;;CDIRS+3O>4SECVTOC ;; L5t}SB of beginning of directory?;;needed in Y!8;; recover read/write request$>FILDIR,Q>FILDIR;;we want to rea5u}d/write thisX;HDSYSIO;;GO DO SYSTEM I/OX;AREAD/WRITE VTOCAX;%X; RDVTOC/WRCTOC - READ/WRITE VTOC X; R5v}DVTOC %>DVDWRQ($Q@VTOCPTR7;; need to write VTOC?20H:RWRTS;; yes...so don't read a new one now!<X;F.X; do we read no5w}rmal vtoc or extended vtoc?PX;Z%ICDNOZ;; drive #d RAMDISKn$Q>DVDRTOP;; top of RAM disk vtocx)>;; is this a RAMD5x}ISK?F:RV3;; yesX;'DCBDRV;; for DHADR call"Q>DCBCST;; status request ('S)PDCBCMD;; also set up& DHADR5y};; call ROM disk I/O routine&Q>DVDVTOP;; assume 810 style drive%DHSTAT;; is it?I:RV3;; yesQ>DVDETOP;; MFM mode5z}:RV3(%ICDNOZ;; once again, drv # (1 to 8),PDRVTBL8;; set vtoc top as drive type$PMAXVTOC;; same thing SETUP d5{}oesX;""X; now MAXVTOC is a useful flag,X;6"X; have to handle extended vtoc@,;; set up for readJ0 EVTOCIO;; read ex5|}tended vtoc (ignore error)T& SAVEEV;; and save it for a moment^!X; (count on A=0 after SAVEEV)h)%>DVDWRQ;; 0-->flag...av5}}oids problemsr+P@VTOCPTR7;; ...with reading junk VTOCs|X;,$ VTOCIO;; then read regular vtoc+ RESTOREEV;; and get5~} extended vtoc back :RWRTS:'X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X; OPEN VTOCX; OPVTOC RDVTOC;;READ 5}IT ;then fall thru to write it!X;'X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;#X; WRVTOC -- write the full VTOC&X;05} WRTVTOC:Q>D%>DVDWRQ;; turn off flag:N)P@VTOCPTR7;; write no longer requiredX% SAVEEV;; then save extended VTOCb5};l) VTOCIO;; while we write regular vtocv& RESTOREEV;; recover extended VTOC;&!EVTOCIO;; and write extended VTOC5}X;#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;-X; VTOCIO -- read/write (based on CLC/SEC)#X; primary VTOC sector5}X;X; VTOCIO QVTOCPTR;; BUF ADDR, high$VTOCPTR;; and lowX;,%>4SECVTOC;; primary vtoc sector # (lsb) X5};$X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X;*,X; DSYSIO -- read/write VTOC or DIRECTORY4.X; sector--buffer addr in 5}X and A>,X; (lsb and msb), lsb of sectorH,X; number in Y (msb always $01)R DSYSIO\ 'DCBSECf%>5SE5}CVTOCp)'DCBSEC;; form full sector addressz;fall thru to SECAXIOX;$X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;)X; SE5}CAXIO -- read/write (CLC/SEC) any/X; sector--buffer addr in X and A,X; (lsb and msb), sector number5}!X; already in DCBSECX; SECAXIOPDCBBUF;; address to DCB &DCBBUF BSIOR;;GO DO I/OI:EVRTS;; 5}good status X; ")>DCBDER;; what kind of error? FDEAD;; data error$ ,!ERRIO;; serial I/O error...user handles. X;8 (5}DEAD@ERROR E.SYS;; tch tch, fatalB X;L *X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;V !X; EVTOCIO -- extended vtoc IO` X;j 5}EVTOCIOt 1QMAXVTOC;; does this disk have an ext'd vtoc?~ (I:EVRTS;; no...so don't try anything X; 6;; save READ/WRITE f5}lag Q>4EVSECNUM "PDCBSEC;; set up sector number Q>5EVSECNUM PDCBSEC;; (both bytes) X; "QVTOCPTR;; (also cal5}led ZDRVA) , &O>EVOFFSET;;; adjust start of vtoc >;; lsb to X QVTOCPTR O>;; msb to A 8 '!SECAXIO;; do I/O5} via buffer at A/X X;( X;2 X;< )X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;F X;P 6X; SAVEEV -- save the 44 bytes of the exten5}ded vtocZ 3X; which are also in regular vtoc aread SAVEEVn (%>DVDVTOP;; 1 byte past regular vtocx :SEV2 Q@V5}TOCPTR7 PFIXEDBITSDVDVTOP8 !Q>;; zero area as we save it P@VTOCPTR7 3 )>DVD2.5;; (144 bytes) H:SEV2 :EV5}RTS : X; ,X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; %X; RESTOREEV -- the 44 bytes again X; RESTOREEV &%MAXV5}TOC;; any point in restoring?" )I:RERTS;; no...leave zero bytes alone, %>DVDVTOP6 :REV2@ QFIXEDBITSDVDVTOP8J P@VTO6 }lar vtocxD:FRE2;; it is regular(%>DVDAUX;; not regular...use aux cnt :FRE2-Q@VTOCPTR7;; clumsy way to bump by one9}...,;; but only way with 6502O>;; instruction set when$P@VTOCPTR7;; using (xxx),Y form.3Q@VTOCPTR7O>9}P@VTOCPTR7X; :FRRTS :X;AGET SECTORAX;"(X; GET SECTOR - GET A FREE SECTOR FOR,%X; USE BY FCB POINTED 9}TO BY X-reg.6+X; The sector number is placed in FCBLSN@X;J)X; THE SEARCH FOR A FREE SECTOR STARTST&X; AT THE DVDSMP BYTE9}. SECTORS ARE^(X; NUMBERED SEQUENTIALLY FROM ZERO TOh2X; MAXVTOC*8-1, WITH THE LEFT BIT OF THE DVDSMPrX; BEING BIT #ZERO9}.|X; GETSECTOR+%>DVDSMP;; start one byte before mapX;:GS13;; to next byte of map&)MAXVTOC;; at end of th9}is map yet?'EGSERR;; yes...no sectors available*Q@VTOCPTR7;; no...try this byte of map'F:GS1;; no free sector in thi9}s byteX;&X; found a byte with a free sector!X;X;.X; before proceeding, let's find bit numberX; and flip the9} bitX;*$>;; simply initializing the bit cntr&X;0 :GSBIT:2;; count a bitDT?;; is this it?ND:GSBIT;; noXX;b9}X; X has bit numberlQBITTBL9;; get the bitv N@VTOCPTR7;; flip it in vtocP@VTOCPTR7;; thusly.X;*X; VTOC bit ma9}p changed, bit # in X-regX;A;; so we save bit number!5;; on stack for a bit of timeX;)X; now generate the sector9} # in FCBLSNX;!$CURFCB;; work with FCB againX;C;; byte displacement to A;%S>DVDSMP;; becomes INT(sector#/8)9} )PFCBLSN9;; prepare to first mult by 8X; 'Q>;; 2 upper bits on=3 left shifts*X;4-X; note that after shifting A th9}ree times,>$X; we will shift out a zero bitH(X; and, if nothing gets shifted in,R)X; A will hold zero. Thus $C0 is 9}as\%X; good as $00 for initial valuefX; of MSByte of LSNpX;zX; :GSLP1 TFCBLSN9;; shift low byte...U?;; ..9}.into high byteE:GSLP1;; 3 times?X;&PFCBLSN9;; and set up high byte7;; recover bit number'LFCBLSN9;; becom9}es part of sector #PFCBLSN9;; thusX;X;2X; now we must decrement one of the sector cntsX; X; which one? X;9} ))>DVDVTOP;; past top of regular vtoc?$ "%>DVDNSA;; assume regular vtoc. D:GS2;; it is regular8 (%>DVDAUX;; not regular9}...use aux cntB +QFCBEFLAG9;; AHA! If this sector is...L &M>;; ...in extended VTOC, then...V %L>;; ...we must change it9}s EFLAG` -PFCBEFLAG9;; to indicated 'extended file'j :GS2t #;;; the only 6502 way to do this~ Q@VTOCPTR7 S> P@VTO9}CPTR7 3 Q@VTOCPTR7 S> P@VTOCPTR7 X; ,X; as long as we are messing with VTOC... X; +%>DVDWRQ;; set WRITE VT9}OC REQUIRED flag #C;; (any non-zero value will do) P@VTOCPTR7 4QFCBLSN9;; for callers: expected of GETSECTOR :;; a9}nd that's it X; X;;;;;;;;;;;;;;;;;;;;;;;;;;;;( X;2 -GSERR@ERROR E.NSA;;NO SECTOR AVAILABLE< X;$'QFCBCSN9;; get ls8hX;SAVE #D9:FMSRAM.M65AMISC STORAGEA @ORG X;%X; MISC NON ZERO PAGE STORAGE AREAX;$%MAXVTOC ;;I} MAXIMUM VTOC INDEX.!RETRY ;;I/O RETRY COUNTER8"ENTSTK ;;ENTRY STACK LEVELB DHOLES ;;DIR HOLE SECTORLDHOI}LED ;;DIR HOLE DISPLV DHFNUM ;DIR HOLE FILE NO`!CDIRD ;;CURRENT DIR DISPLj"CDIRS ;;CURRENT DIR SECTORtI}SFNUM ;;FILE NUMBER~'SVDBYT ;;SAVED OUTPUT DATA BYTE#EXTSW ;; flag for FN DecodeTEMP3 ;;TEMP3TI}EMP4 ;;TEMP4,WILDFLAG ;;WILD CARD CHECK IN RENAME5DIRCPTR ;;CURRENT CHAR IN FORMATTED DIR ENTRYX;'SIOI}CMD ;; saves value of DCBCMDBURTYP ;;BURST I/O TYPEX;DRVTBL ;;DRIVE TABLESECTBL ;;DBUFAL I};;VTOC BUFFER DBUFAH ;;PTR FOR DRIVE N 7SBUFSTART ;; ADDRESS OF START OF SECTOR BUFFERSFNAME  ;;FILE NI}AME(NEWNAME  ;;USED BY RENAME ROUTINE(>BURSTFLAG ;; FLAG TO INDICATE BURST I/O WAS SUCCESSFUL2X;<(FIXEDBITS I},;; saves extended vtocFAFILE CONTROL BLOCKSAPX;ZX; FILE CONTROL BLOCKd-X; ONE FILE CONTROL BLOCK IS USED FOR EACHI}X;SAVE #D9:FMSSETUP.M65ASETUP ROUTINEAX;-X; SETUP - A ROUTINE USED FOR ALL COMMANDS"X; TO SET UP FMS CONTR=}OLL CELLS"X; TO ACCESS A PARTICULAR FILE.$X;. SETUP8 &CURFCBB@L2V2` &ENTSTKjX;t$ICDNOZ;;MOVE DRIVE NO~=}&DCBDRV;;TO DCB0;;DEC FOR ACCESS TO TABLESQDBUFAL9;;MOVE WRITE BUFFER"PVTOCPTR;;ADD TO ZERO PAGE PTR QDBUFAH9=}PVTOCPTRX;QDRVTBL9;;GET DRIVE TYPEFERRDNO;;BR IF NOT EXISTS0PMAXVTOC;; otherwise, set maximum VTOC index=}X;$CURFCB;; GET CHANNEL AGAIN%FCBBUF9;;GET SECTOR BUF #!H:SU3;;BR IF ONE IS ALLOCATED X;":SU1QSECTBL8;;TRY =}TO FIND ONEI:SU2;;BR ONE FOUND(3;;DEC TRY COUNT2)><D:SU1;;BR MORE TO TRYFX;P2ERRNSB@ERROR E.NSB;;NO SECTO=}R BUFFERS AVAILZX;d:SU2Q>;;ALLOCATE BUFFERn PSECTBL8x3C!PFCBBUF9;;PUT BUF NO INTO FCBX;&:SU31;; NOW CO=}MPUTE BUFFER ADDRESS"C;; BY MULTIPLYING INDEX BY 128V?5Q>W?;; A NOW = 0 OR $80, C = 00OSBUFSTART;; AND ADD=}ING BUFFER START ADDRESS PZSBA7OSBUFSTART PZSBAX;JMP SUVTOC:"X;,'ERRDNO@ERROR E.DNO;;BAD DRIV=}E NO6@X;JX; FREE SECTOR BUFFERSTX;^ FRESBUF h%FCBBUF9;;GET BUF NOrFFSBR;;BR IF NONE|1;;DEC FOR TBL ACCESS=} Q>;;FREEPFCBBUF9;;IN FCBPSECTBL8;;AND TABLE FSBR:X;ADATA SECTOR I/OAX;X; DSIO - DATA SECTOR I/O=}X;DSIO$ZSBA;;WRITE SECTOR BUF&DCBBUF;;ADR MOVED TO$ZSBA;;DCB&DCBBUF!BSIO;;DO THE I/OX;NTR<zX;SAVE #D9:FMSDOS.M65AWRITE DOSAX; X; WRTDOS - WRITE DOS TO DISKX; WRTDOS$%FCBCSN9;;MOVE START ADDRA}.QFCBCSN98! SETDSO;;WRITE SECTORS 1 TO 3B WRDOSSYS;;WRITE DOSL !GREATVX;` DELDOSjQ>;;SET FILE NOT EXISTSA}t WRTBOOT~ PDFSFLGX; Q>FMSORG;;MOVE FMS STARTPDCBBUF;;ADDR TO DCB%>FMSORG 'DCBBUFX;4X; !!A}! caution: ASSUME Y-REG IS ZERO !!!!!!!!!!!X;WRNBS3;;INC SECTOR NOQ>; BSIO;;DO THE WRITEX; 'QDCBBUF;A}; ADD 128 TO BUFFER ADDRESSN> PDCBBUF( G:WRB12#DCBBUF<X;F!:WRB1%DCBSEC;;TEST FOR WRITEP)BRCNT;;OF ALLA} BOOT SECTORSZHWRNBS;;BR NOT ALLdX;n:xX;"SETDSO'DFLINK;;SET LINK STARTPDFLINK"Q>;; SET DOS FLAG TO NOA}N-ZEROHWRTBOOT;;GO WRITE SECTOR 0X;4WRDOSSYS MOVESTART;; MOVE START OF DOS TO ZBUFP#Q>};; SET SECTOR MAXIMUA}M LENGTH PFCBMLN9X;3:WRDOSLOOP MOVEDATA;; MOVE NEXT SECTOR OF DATA QZBUFP;; TEST FOR END OF DOS RSASA QZBUA}FP SSASA E:LASTSEC"X;,( WRTNXS;; NOT THE LAST, WRITE IT OUT6!:WRDOSLOOP@X;J7:LASTSEC:;; JUST RETURN SOA} CLOSE WRITES LAST SECTORTX;^ATEST DOS FILE NAMEAhX;r*X; TSTDOS - TEST FOR DOS SYS FILE NAME;|X; TSTDOS($>;A}; begin looking at start of name,%CDIRD;; current directory sector offset :TDOSLP0QFILDIRDFDPFN8;;TEST FILENAME inA} Directory'RDFN9;;WITH "DOS.SYS" FILENAME CHARH:TDFR;;BR NOT MATCH3;; to next char in DIR2;; to next char in DOSA}.SYS(> ;; 11 characters yet?%H:TDOSLP;;BR IF MORE, ELSE RTN EQ :TDFR6;; must save status!$$CURFCB;; a must foB} AERROR ROUTINE AND CLEANUPAX;X; ERROR ROUTINESX;'ERROR7;; RETRIEVE ERROR NUMBER FROMPERPTR;; JSR AREE}A$7. PERPTR8%>B Q@ERPTR7L X; AND FALL THROUGH TO RETURNVX;$RETURN$ENTSTK;; GET ENTRY STACKB;;AND RESTOE}RE $CURFCBPICSTA9;;PUT IN FCB? QSVDBYT;;GET SAVED DATA BYTE:X; %ERRIOQDCBSTA;;GET I/O ERROR CODE GREE}TURNX;(FGREAT$CURFCB2 FRESBUF;;FREE SECTOR BUFFER<GREATQ>;;SET ALL OKF HRETURNdX; FROMPERPTR;; JSR AREDdn'X; OPEN FILE. THE RELATIVE FCB USEDx$X; RELATES DIRECTLY TO THE IOCB #+X; THAT OPENED THE FILE. THUS THERE ARE'X; 8I} FCBS. THE FCB ARE (CONVIENTLY)'X; THE SAME SIZE AS IOCBS. EACH FCB+X; CONTAINS ALL THE INFORMATION REQUIRED%X; TO COI}NTROL THE PROCESSING ON ANX; OPEN FILEX; @ORG X;FCB&FCBFNO ;;FILE # LEFT JUSTIFIEDFCBOTC ;I};OPEN TYPE CODE#DFDOUT;;FILE OPEN FOR OUTPUTHDFDLOCI} ;;ENTRY LOCKEDR0DFDNLD;;FILE HAS NEW TYPE SECTOR LEN BYTE\6DFDEXT;; "EXTENDED" FILE (INVISIBLE TO DOS 2.0SfX;pI}X;zAVOLUME DIRECTORYAX;X; DISK VOLUME DIRECTORY/X; THE VOLUME DIRECTORY OCCUPIES THE CENTRAL*X; VOLUME SECTOR. I} THE VOLUME DIRECTORY(X; CONTAINS INFORMATION PERTAINING TO!X; THE ENTIRE DISKETTE VOLUME.X;&X; THE LABELS BELOW, MAI}P THE VOLUMEX; DIRECTORY SECTOR.X;-DVDTCD;;VOLUME DIRECTORY TYEP CODE )1)X; X; USED TO DELINATE MAJOR (1) I}X; FMS SYSTEM FORMAT CHANGES X; $DVDMSN;;MAX SECTOR NUMBER (1)$ (DVDNSA;; cnt of sectors available. X;8 DVDWRQI};;WRITE REQUIREDB DVDSMP ;;SECTOR MAP STARTL X;V 2DVDRTOPDVDSMP ;; top of RAMDISK vtoc` 2DVDVTOPDVDSMPI} ;; top of regular vtocj 0DVDETOPDVDSMP ;; top of ext'd vtoct 3DVDAUXDVDETOP;; aux cntr of sectors availaI}ble~ X; (DVD2.5;; size of version 2.5 vtoc (DVD2.0;; size of version 2.0 vtoc X; 7EVOFFSETDVD2.5DVD2.0;; dI}ifference in VTOC sizes X; "X; EACH BIT REPRESENTS A SECTOR &X; IF THE BIT IS ON THEN THE SECTOR $X; IS FREE AND AVAILABI}LE. IF THE "X; BIT IS OFF, THE SECTOR IS IN 'X; USE OR BAD. THE MOST SIGNIFICANT +X; BIT OF THE FIRST BYTE IS SECTOR ZERI}O.. IF THE "X; BIT IS OFF, THE SECTOR IS IN 'X; USE OR BAD. THE MOST SIGNIFICANT +X; BIT OF THE FIRST BYTE IS SECTOR ZERHX;SAVE #D9:FMSRAMIO.M653A Simulated Sector I/O to RAMDISK (130XE)AX;!RAMDISK;; only if asked for!X;a}X;SAVE #D9:FMSBANK.M65X;X; RAMDISKX;-X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$X;.$X; RAMSYNC -- en]}sure RAMIO occurs8*X; only with interrupts disabled andBX; during VBLANK intervalLX;V RAMSYNC`%>j+'CRITIC;]}; tell VBLANK this is critical!t.$FASTRAM;; special: ignore sync w/ vblank?~G:FASTER;; yesX; $CLOCKLSB :SYNC!]}(CLOCKLSB;; got a VBLANK yet?F:SYNC;; noX; :FASTER 'NMIEN;; disable VBI and DLI=;; and disable IRQ'sX;^}X;$/X; first, some equates unique to RAMDISK I/O.X;8 ZSECPTR2;; share with SIO!B0ZRAMPTRZTEMP1;; share with erroa}r exit ptr!LX;V"MAINMEMORY;; per Atari spec`X;jX;tX; do RAMDISK sector I/O!~X; RAMIO QDCBSEC PZTEMP1;a}; must be preserved!6;; save read/write flag+QDCBSEC;; high byte of sector number/X; (ramdisk sector # is 1 througa}h 511, $1FF)X;+TZTEMP1;; 128 sectors=16K bytes, a bankU?;; so A has bank numberX; (safety check)(R>;; A musb } EI=EF D2:FMSEQU.M65XM}; .ERROR "D2:FMSBOOT.M65">D2:FMSBOOT.M65X; .ERROR "D2:FMSBSIO.M65">D2:FMSBSIO.M65X; .ERROR "D2:FMSSTAT.M65M}">D2:FMSSTAT.M65X; .ERROR "D2:FMSINIT.M65">D2:FMSINIT.M65X; .ERROR "D2:FMSOPEN.M65">D2:FMSOPEN.M65XM}; .ERROR "D2:FMSBYTE.M65">D2:FMSBYTE.M65X; .ERROR "D2:FMSCLOSE.M65">D2:FMSCLOSE.M65X; .ERROR "D2:FMSFMT.M6N} $: AEntry point error! Can not be placed where needed!A.'SPACE  ;; GET PURPOSEFUL ERROR!8B-SPACE   ;}; !!! available space !!!L V`jX;t%X; macros to generate 1 and 2 byte~X; unconditional branches#X; (actually}X;SAVE #D9:FMSSTAT.M65 ASTATUSAX; X; DFMSTA - GET A FILE STATUSX; DFMSTA$ SETUP;; SETUP.2 NEEDFILEQ};; decode, find, and insist it exists8 TSTLOCK;;TEST LOCKEDB$!GREAT;;FILE EXISTS AND UNLOCKEDLX;P;; SETUP.2 NEEDFILEPg EI=EF D2:FMSEQU.M65 AD2:FMSBU}OOT.M65A>D2:FMSBOOT.M65 AD2:FMSBSIO.M65A>D2:FMSBSIO.M65 AD2:FMSSTAT.M65A>D2:FMSSTAT.M65 AD2:FMSINIU}T.M65A>D2:FMSINIT.M65 AD2:FMSOPEN.M65A>D2:FMSOPEN.M65 AD2:FMSBYTE.M65A>D2:FMSBYTE.M65 AD2:FMSCLOSEU}.M65A>D2:FMSCLOSE.M65 AD2:FMSFMT.M65A>D2:FMSFMT.M65 AD2:FMSXIO.M65A>D2:FMSXIO.M65  AD2:FMSDIR.M65A!V}>D2:FMSDIR.M65" AD2:FMSFNAME.M65A#>D2:FMSFNAME.M65$ AD2:FMSSRCH.M65A%>D2:FMSSRCH.M65& AD2:FMSRWSEC.M65A'V}>D2:FMSRWSEC.M65( AD2:FMSVTOC.M65A)>D2:FMSVTOC.M65* AD2:FMSALLOC.M65A+>D2:FMSALLOC.M65, AD2:FMSSETUP.M65V}A->D2:FMSSETUP.M65. AD2:FMSDOS.M65A/>D2:FMSDOS.M650 AD2:FMSEXIT.M65A1>D2:FMSEXIT.M652 AD2:FMSBANK.M65A3V}>D2:FMSBANK.M654 AD2:FMSRAM.M65A5>D2:FMSRAM.M656 AD2:FMSRAMIO.M65A7>D2:FMSRAMIO.M658 AD2:FMSEND.M65A9>V}D2:FMSEND.M65:AMDISK;; Version for 128K machine w/ 64K as ramdisk?  AD2:FMSEQU.M65A >D2:FMSEQU.M65 AD2:FMSBTINAL ADDRzPLMADR;;TO LOW MEM PTR QZBUFP PLMADRX;X; CLEAR FCBS TO ZEROX; CLRFCB Q>;;128 OF FC}B?CFCBXPFCB8;;TO BE CLEARED3 ICFCBXX;?;; AGAIN SET Y TO ZERO ADI1QDEVTAB8;;FIND AH FADI2;;UNUSED }R> D;;OR DISK$ FADI2;;EMPTY. 38 3B 3L )>V HADI1` +;;ELSE BREAKj X;t ADI2Q> D;;SET DISK~ PDEVTAB8 Q>DFMSDH};;SET FMS ADDR PDEVTAB8 Q>DFMSDH PDEVTAB8 X; :MSDH - DISK FILE MANAGEMENT DISKX; HANDLER ENTRY P H4b !GREATVE #D9:FMSXIO.M65 ARENAMEAX;%X;XRENAME - RENAME A FILE OR FILESX; XRENAME$ FNDCODE;; get past ol E LO :;SAVE #D9:FMSDIR.M65ALIST DIRECTORYAX;"X; LISTDIR - LIST THE DIRECTORY%X; GDCHAR - GET NEXT DIR CHARACTER$CPTR7T 3^ )>DVD2.5;; (144 bytes)h H:REV2r :RERTS| :&X; RDDIR/WRDIR READ/WRITE DIRECTORYX;$ RDDIR.,;;SET READ4;t have a value of 0 to 3!D:SECOK;; phew!8;; clean up stack .%>E.NAK;; "disk" didn't like sector number"H:RAMRTS;;b } return with boo-booX;( :SECOK2, RAMSYNC;; synchronize with VBLANK, etc.<;(also sets up bank select)F%QZTEMP1;; bb}ecause of ASL above...P.;...A has sector remainder (0-127) times 2Z;;; this is sneaky:dW?;; high bit of A is setn,V?;;b} A=01xx xxxx, where xxxxxx is senum/2x6PZSECPTR;; forces address to $4000-$7FFF range!Q>W?;; A gets $00 or $80b}'PZSECPTR;; neat? a perfect pointer+X; address of RAMDISK "sector" is set up QDCBBUF PZRAMPTRQDCBBUF/PZRAb}MPTR;; set up pointer to data bufferX;%>;; 128 bytes in a sector8;; read or write?D:READRAM;; read requestb}X;X; write sector to RAMDISKX; :WRITERAM""Q@ZRAMPTR7;; move 128 bytes...,P@ZSECPTR7;; ...to RAMDISK61@I:b}WRITERAMJG:RAMJN;; all bytes writtenTX;^X; read sector from RAMDISKhX;r :READRAM|Q@ZSECPTR7P@ZRAMPTR7;; movb}e 128 bytes1 I:READRAMX;X; clean up RAMDISK I/OX; :RAMJN9Q>MAINMEMORY;; deselect RAMDISK, select normal b}memory SETBANK;; thuslyX;X; reenable interrupts, etc.X;%>#'NMIEN;; enable VBI's and DLI's%>$'CRIb}TIC;; no longer critical I/O&.;; and IRQ's are now legal0$3;; now Y=1...a good return value:X;D :RAMRTSN:X!X;`vX; fall thru to SETBANK...we#X; didn't disturb A-register!X; =X; SETBANK -- subroutine to set PIA to proper RAMDISK ^}bankX;$X; enter: A-reg has 0,1,2,3 or 4(X;2 SETBANK<T?F&T?;; get bank number to proper bitsP'PZTEMP2;; and hol^}d them for a nonceZ'QPIABPORT;; the memory control bitsd#M>;; zero out bits PB2,PB3,PB4n'LZTEMP2;; then include our ne^}w bitsx&PPIABPORT;; and reconfigure memory:X;d#M>;; zero out bits PB2,PB3,PB4n'LZTEMP2;; then include our ne\9 just first bytes of&X; BIT zeropage and BIT absoluteX; @SKIP1  $X; @SKIP2  ,X; Notice u5">D2:FMSFMT.M65X; .ERROR "D2:FMSXIO.M65">D2:FMSXIO.M65 X; .ERROR "D2:FMSDIR.M65"!>D2:FMSDIR.M65"X; .N}ERROR "D2:FMSFNAME.M65"#>D2:FMSFNAME.M65$X; .ERROR "D2:FMSSRCH.M65"%>D2:FMSSRCH.M65&X; .ERROR "D2:FMSRWSEC.M65"N}'>D2:FMSRWSEC.M65(X; .ERROR "D2:FMSVTOC.M65")>D2:FMSVTOC.M65*X; .ERROR "D2:FMSALLOC.M65"+>D2:FMSALLOC.M65,N}X; .ERROR "D2:FMSSETUP.M65"->D2:FMSSETUP.M65.X; .ERROR "D2:FMSDOS.M65"/>D2:FMSDOS.M650X; .ERROR "D2:FMSEXIT.MN }65"1>D2:FMSEXIT.M652X; .ERROR "D2:FMSBANK.M65"3>D2:FMSBANK.M654X; .ERROR "D2:FMSRAM.M65"5>D2:FMSRAM.M656XN!}; .ERROR "D2:FMSRAMIO.M65"7>D2:FMSRAMIO.M658X; .ERROR "D2:FMSEND.M65"9>D2:FMSEND.M65:5" >D2:FMSEQU.M65XLd)5ANXcoyʄք !-&;GASZ*}i@L}5 _$% l0$)$$Hȱ$ UhL" `e$$%`$%`l  Rn$}@W!( L(1   Y I`  d  Ld M * @ d $ n%}% CC$$)%1 Udߥ$9%: !0 S$% DD˙`n&}e`  }J)Lr J  ((  p L ()   JL= ( L n'} 0q A    IB JC;? D W  LL n(} a ` W )L A!  ߰")-݆ p" $n)}G@LL 08`Q")<2Q0 -G$Ș݆ UL# ; p8(()(0ʥ)NQ`$GȘ݆LUn,}]hs~̄؄S*4?JU`kvZ+} DŽ݄҄ %1=IUhSNaSNmSNySNSNsSN Z2} )L ݆ L GȘ ݆L L * )W>Z   HH)H p h n-} hyhy D L> L JJ    ! LA*`+ & BF7'n.}8  M HN H` 8 Z  \LdJJ!"! GFE@F (!Ln/}EE !E^ ^ E E7EȩEdE/EȩE ' 8  Dn0} .L9 4 }  ;F d  ;?F7F? ( .   Z D LL d n1}  . D  L    p  E` , d)  D L) 0BM݊L݉n8}SNSNcʄք)5 AMx[gs &5yZ3}ń҄܄҄ Ņ 4$0;FQ^jwĄχچ򅅇)Z4}8 )  -8DP\hr~8~XZ5}Ԅ脇:ڄB.$/:)/UXc!nZ6}yyocc܅ͅ$ڄB8P ڄBZ7}-,hhP8S_k-w8DDŽZ>} 5 q ML  N݆ L NLMLr m [ TEqEHȱEqEh 0Gn9}ȹ G HLL GɛL  LFREE SECTORS G) *Gȩ GȽG GȌ*jn:}j >G;; did 5 bytes yet? H:VTSLP;; no X; (X; now, we have to s"C}et up the bit map X; X; %>DVDSMP;; start of map" Q>;; for first sector, :BITLP6 P@VTOCPTR7@ ,Q>;; all other s"D}ectors get all one bitsJ 3T -)MAXVTOC;; wasn't it nice we set this up?^ H:BITLPh X;r (X; we have to special case a few b"E}its| X; $%>DVDSMP-;;DEALLOCATE MIDDLE 9 Q> P@VTOCPTR7;;FOR 3;;VTOC AND FILE DIR Q> P@VTOCPTR7 X; 1X; "F}now, RAMDISK and regular VTOC are set up... !X; ...but what about MFM VTOC? X; %$MAXVTOC;; just to test the value I:F"S} 腄 hhSN    V  " . 8 D N .y .  Y p p̈́  D eć ZN}}G)݁,G)ȱGȱGHh0})Hh` B! 8`A 8ii(ZE6!JS SdnI}!  E  ` TE 8  8LFEh   r9L )  EiFi(LdEnJ}E` dE` H)h/H^ji hEEdEiEȱEiE` WE QEEHI8 nK}*hd ) 8EEȱEEE` I !ʽ)E1F5I!  nL}!ȘJHjm9Ghm:H`  !`GHLl Z dLȩ8 lI0 `nM} _} ; $ %  pLl`ݚ I(`DOS SYShChDC IC`0I B0n\}  N p q } q    " 턇& 8 a "a m a m ZO}  " 󅄺    #  " / } Շ   e / E 9 E 9 " 9 C 9ͅ  V ZP}O p [ g t  y   9 E 9 E      A  O  [ p ZQ}O O t Ї Ą Є ܅s   "/ <GT`  kZR}xwAM҄UknχA C $Z[}MTNX;; not extended X; extended! (%>DVDVTOP;; we deallocate sector 720 P@VTOCPTR7;; for safety X;& )%>DVDAUX;; wher"T}e extended count goes!0 /Q>4 ;; # of sectors in extended area: P@VTOCPTR7;; LSB...D 3N Q>5 X P@VTOCPTR7"U};; ...and MSBb :FMTNXl X;v X; vtoc is ready to use  WRTVTOC;; so write it out! X; 2X; now, we need to ensure the di"V}rectory sectors X; are filled with zero bytes X; Q>;; thusly... ? %XF3PFILDIR8;;USE FILE DIR BUFFER 3 IXF3"W} X; #Q>;;WRITE TO ALL 8 DIR SECTORS PCDIRS XF4 WRTDIR "CDIRS IXF4 X;*  DELDOS;;SET NO DOS4 X;> !FGREA"Z}X;SAVE #D9:FMSEND.M65AEND OF FMSAX; ENDFMS X;)X; space for who knows what, including$X; MINIDUP ifY}f needed.X;8 @ORG @BX;AEND OF FMSAX; ENDFMS X;)X; space for who knows what, including$X; MINIDUP idT;;DONEX;SAVE #D9:FMSFMT.M65ADEVICE DEPENDENT COMMANDAX;-X; DFMDDC - DEVICE DEPENDENT CMD EXECUTIONX; DFMDDC$  xkAk (Ŝk>kŅ W>W> w{    A  Z]}x D)D` C C*(> C8jJ3j2CD( C202C ԠBX`B0lr" + | + " | ! A: F/S s |^^ A:Z}@_LBL@"#$$c(c(c(c(c(KD # <Qj_}AD8j`}ja}jb}LGBLELEL+DL>ELF,^`LDLBLBLBLBLCLCL7FLCLL$CL*C? &Gr@? HR RF D0jc}$~ F= r@ ELRB BLRB 3D ,F~ iE pH VC 6Eɛ,/H FLGhA[ Bբ BLB8A LHLH`Ɵ` jd}D D D` F`LGL0F eHLDH ZHLOH 6EƟɛ,/`Ġ (` B B sC je}LRB B sC0` D800  ţ` B @C0 ~ iE` 6EɛA+-H Dh+ oFLC }HLCƟ D jf}6E+-Ɵ` Cв CL!D 0Cii` C` F 0C C` DLHr@ pHd@օ@ B @jg}C0,*ŧ&~ Ɵ iELZDĦ iELZD BLZDHh` 0CLG` 6E. FƟ@ 6EX D DeeLDƟ D`jh} C L@C B$ G` F wC Ɵ* wC!  GeiL EƟ` D ` ` ED Hji} Ch`LRFHHH BLRBCɛB ɀ.H Bh LGBB BB ( BƵhhh`LG6jj}LGHE G. iEh`}~ gEɛ iE`=2(.)* gE 7F 7F  7FHJJJJ @Fh)ii@LiE$0jk} HH iE`qq`LiEB@ BLGLHŁŀ`FLG=ASXZ`}LiE66jl}&&8HYehYeƤհyy` gE RF RF R BLRBc$d%BBB  jm}@#@bA @ @ @ @ eH膬 F RFG iELB Copyright 1982 McStuff Co.ш`jn}&&66 H oFhƤ襎`LFHH`X@ #H`@ @@A@@`6jo};@`6@`6;@`6@`Hr@h`8񐕀񐕁`a{)`ɀɶ ii?`> ERROR!jp}BUG/65 Version 2.0COMMANDIMMMEDIATE CMDPROTECTIONPARAMREGISTERBREAKPOINTPRINTERSYNTAX*** ERROR - MNEMONICOPERANjq}DRANGETOO MANY LABEL REFSUNDEFINED - I/O ERROR - = USER RUNBREAK! A X Y SP NV_BDIZC PC INSTRADANASBCBjr}CBEBIBMBNBPBRBVBVCLCLCLCLCMCPCPDEDEDEEOINININJMJSLDLDLDLSNOORPHPHPLPLRORORTRTSBSESEjs}SESTSTSTTATATSTXTXTY**a! 0PpXʈAL BHh("b@`8x  jt}      Jx x x x d B x x x x x x x Mx x ju}x x x x x f g x x x x x x lx x x x ix x x x c ` x x x x x x Oxjv} x x x jx x x x e h x x x x x x nx x x x x x x x Vx ux x x x x wjw}vx x x x  x x s rx x x x x Ptx x x x x Z Ux x x x x xjx} Nx x x x x x x Y ax x x x x x mx x x x 5MMMNNNNNO=O[OOPPPPPP9M_QbQQjy}Q.RRRLG D0rp OE @C0hf ,F F LF F C @C0F FLWM_ ƂƃLqM $ @ CLM OEjz}惥ɛТ` D` C VC FB H Hь F bE )F "F bE 7F GLM` C Diij{} VC Fg F H )FƤ G 奤 ,F ,F ,FƤ H EƤ G j|}L5N` R pH Sdɛ R?LB C D VC F G`LS C D oF F }HL0F gE8OVAj}} SLR S0 iE VCL'OLRD:*.* R Dɛ DH %Shɛ RLRB C gEH  Fi0Hh iELO` gE C 0C j~}VC FqH 0ChhH(DŋNŊF 6E*&Ɵ C H拱ň恥ТLO "FLO j}0C` C~x }H扢Ł'ŀ oFƄƅ VC HH Fh oFj} oFƈƉ`LGB`B` 0C DSƫPƬ`LG@ @ Pl l R -S D R SZ SS Sj}򥀍AAeeee SH Fh G S0LRLRLT C ZH OH>@?@QHzHl<@ eHLDH RF@ )Fj}Q0-A1 iE ,FAA "F ,FAA -ULgE @W -S 6E: DAB ƟH ChH Rh %S %Sj} %S H %S GLRLG D @C0PN R ,FR iE F B @C053 $ iE OE @C0$HR@Ahɛ Lj}QR GLGR`AXYSPFLTL8XH 6E#7 0C DVA#VAh S0` RF bO R BLRBLG ZRLVZj}VTAU S0`XYբ S0`H 6E'"hƟ`hhh'   @ D&   j}D DW@ YLRmm   Ƴƴ` #H膖膄 T@Ɵ CAA j}T@LG C TR D Rۆ T C TI T D愢 RF@@@eTLW0@Ƅƅj} VLOT RFLQ 0ChhLJTLD D=LT` DSƚƟ D VC V QƄƅ` C C VC F ,F ,FHH -Uhhj} ,F椥 W H )FƱ쥄 F` VH)? I0IH) iEh ,F ,Fh lU{UHzUH`  j} UUUUUUUUjUjUUUUU VL0FXYH UhLV VL7FXYH V 7FLU F V 7FX VLF F V 7F FYLV# iELU WL0j}F F ULF HL7F V V` HJ&& oFȱ`،A@h@h)Ah8AhAA@@@j}@X eH DH #Hl@H, iEhLiE恢 H`@ @#@@ FAцц`LGAA V @)? vLWj})LW*LW Wei@@ՠTLWH WhH Wh) TW-AL WTW-A壟@@LW@L W  j}VLGW V H HL WLVA膂膂L WA膂膂L W VHheej}`JJJJJJ`@@ V ZH OH@@@=VAAHAHAH@@A@ D0CA OE: gEPA F ,F ,F C j}@C0 ED XLUX j]` 6E/+(Ɵ X Y Y \% :]` \LX \ +]LX  H RFh RF` \Aj}L9ȱ02:.)ȱ # AAAA`AŴAAH) \7Hj} FhLY惢 F FhAС Z ,FA iET iE ,F 0FhL0Y \7I)ђ ȽI0轱I轱I*ܱj} ɛ` LX g[eJ JJŲ򦱽J93 J 9ZH8ZH`mZaZaZ[Z[ZaZ[Z^Z[Z^ZdZ[ZsZZ`j} LX Z ZLZ Z ZLZ G Z Z9 Z Z+ `聾ᥲ ZHZH`Z[[,[6[6[:j}[>[B[H[P[Za[ 2] \!LXJ &] +] +]LTZJ ܩ &]L[ 2]LTZ &]LTZj}JL/[ L [ F \ 5\ \ }\`H 6EL D0 :)L[L/\ AAaZAA A0j}< XLRBiAAA慦J慩L)\H 6E# \ h`h`H [&hH 6E.Xj}0*:A"GƟ C \ \L)\L/\H 6E(5 >\0& D) D) \ L)\L/\XYj}, ȊђȄ` >\` \` 6EƟɛ` }HƄƅƄƅ0 0 `0`]J`]JL+]+ ,j}F F膂 )Fƭ` A6A/ RFL iE 0 iE ,F RF? iE D0 OE #Y津 `j}j}j}j}j}QhIS * s i t  ՄSŅ < 8G  A:  Z}܄j T p  p  p E E % "00%9w Z}r some caller8;; answer to is it DOS.SYS?:&X;0DFN ADOS SYSAO DISKX; WRTDOS$%FCBCSN9;;MOVE START ADDR@K PZBUFP:X;SBOOT.M65ABOOT RECORDA FMSORGX;$X; THE FOLLOWING BYTES ARE STORED$X; ON DISK SECTOR 0 THE 0 ̈́E; ` ͅ ) 6i{u{Ŧ҇"ͅ # e Z} :ͅ>  ҄ ҇ $  ҇ Һ     ^Z} & &x腄yZnynn>n + +܄F   6  Z} ք:    ' ' :? +I :I? S Z} ÄS :܄_ 6 ˅ 8 p{ p  Մ{ * g G҄ E ;҇ E Z}  C Y Є Y E E ; "  E E p 8 E EȄ;Z}  E E ܇ " Ąs   $ $ A$ /iSZ}U5ywU>Q^Sjv i0 S^jvQjŇ/Z}$  jQ>Ň ^ww( v>ww(Z}Wwu{Ņ *W>ŇlŦ܇W E E E E E wu{ Z}SŇ E . U_k@>Lv nL҅@ Z} ^LL҇ޅ !̈́~))އ  !Z} " hh 8 | ܄  C ~   C  CZ}  օ2.ڄB$> Ä ք τ n&DŽ҄y Z}_k + ڄBބ   ܄ p " ĄL E 9; ЄGG A VZ}  y d Y  S _t  'k wuSWWwWW{Z}((X  ".ʅrڄBZ} օ2.ڄB$> Ä ք τ n&DŽ҄y XOR E.FN;;filename error X;me is decodedX;X;&X; oops...no characters in filenameX; ERFNAME :FNERR !@ERR(