þþÃèX;SAVE #D9:FMSEQU.M65ò6A¯FMS - 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, California8X;B)X; THIS PROGRAM MAY NOT BE REPRODUCED,L&X; STORED IN A RETRIEVAL SYSTEM, ORV&X; TRANSMITTED IN WHOLE OR IN PART,`)X; IN ANY FORM, OR BY ANY MEANS, BE ITj*X; ELECTRONIC,MECHANICAL, PHOTOCOPYING,t)X; RECORDING, OR OTHERWISE WITHOUT THE~!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-3099ºX;ÄX;Î(X;***********************************ØX;â&X; Originally designed and coded byì7X; Paul Laughton of Shepardson Microsystems, Inc.öX;*X; Modified for Atari 1050 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; === Universal Atari OS Equates ===ŒX;–B…OSBTM5à ;; OS ROMs always call FMS from $E000-$FFFF ??? (†FMSORG;; normal boot-in locationª,†FMSZPGC;; seven bytes reserved for FMS´X;¾+‡IOCBORG@;; 8 IOCB's of 16 bytes eachÈ)„ZICB ;; current IOCB is copied hereÒ…LMASK;;LINK MASKÜX;æ&†DCBORG;; command block for SIOð"„SIOVYä;; vector for SIO callúX;,…DHADRSä;; vector for resident disk I/O0†DHSTATê;; where DHADR returns disk status4†DSKTIMF;; format disk time out (DHADR result)"X;,1ˆPIABPORTÓ;; data port, memory select, etc.6'ƒEOL›;; ATASCII "Return" character@7…LMADRç;; pointer to bottom of application memoryJ)†DEVTAB;; device name & addr tableTX;^!†CRITICB;; critical I/O flagh2…NMIENÔ;; NMI disable/enable (1-bit enables)r,ˆCLOCKLSB;; lowest byte of jiffy clock|X;†X;6X; === Equates Preserved by FMS in all versions ===š!‡SECVTOCh;; where regular V¤.ˆEVSECNUM;; becuz DOS only uses to 1023®X;¸+‡DUPINIT@;; initial addr for mini-DUPÂ-„STAK;;stack offset of FMS caller addrÌ,†TIMOUT;; time out for normal disk I/OÖX;à'X; Size of VTOC in MFM mode on 1050:êX;ô5ˆVTOCSIZE;; 10 (header)+128 (bit map)+6 (evtoc)þX;$X; LENGTH OF SECTOR AND NUMBER OFX; DATA BYTES:X;& †DRVMDL}0 †DRVLBT:X;DA‰ IOCBAN ‡IOCBORGXX;bX; IOCB - IO CONTROL BLOCKl$X; THERE ARE 8 I/O CONTROL BLOCKSv!X; 1 IOCB IS REQUIRED FOR EACH€#X; CURRENTLY OPEN DEVICE OR FILEŠX;”„IOCBž…ICHID ;;DEVICE NUMBER¨…ICDNO ;;DEVICE HANDLER²…ICCOM ;; I/O COMMAND¼…ICSTA ;;I/O STATUSÆ…ICBAL Ð …ICBAH ;;BUFFER ADR (H,L)Ú …ICPUT ;;PUT CHAR DH ADDRä…ICBLL î …ICBLH ;;BUFFER LEN (H,L)ø†ICAUX1 ;;AUX 1†ICAUX2 ;;AUX 2 †ICAUX3 ;;AUX 3†ICAUX4 ;;AUX 4 †ICAUX5 ;;AUX 5*†ICAUX6 ;;AUX 64…ICLEN „IOCB>X;H( …ICLEN;;SPACE FOR 7 MORE IOCB'SRX;\X; ICCOM VALUE EQUATESfX;p…ICOIN;;OPEN INPUTz†ICOOUT;;OPEN OUTPUT„„ICIO;;OPEN UN/OUTŽ…ICGBR;;GET BINARY RECORD˜…ICGTR;; GET TEXT RECORD¢…ICGBC;;GET BINARY CHAR¬…ICGTC;;GET TEXT CHAR¶…ICPBR;;GET BINARY RECORDÀ…ICPTR ;;PUT TEXT RECORDÊ…ICPBC ;;PUT BINARY CHARÔ…ICPTC ;;PUT TEXT CHAR Þ‡ICCLOSE ;;CLOSE FILEè†ICSTAT ;;GET STATUSò…ICDDC;;DEVICE DEPENDENTü…ICMAX;;MAX VALUE "†ICFREE;;IOCB FREE INDICATOR X; X; ICSTA VALUE EQUATES$ X;. $…ICSOK;;STATUS GOOD, NO ERRORS8 …ICSTR;;TRUNCAIATED RECORDB †ICSEOF;;END OF FILEL †ICSBRK€;;BREAK KEY ABORTV †ICSDNR;;DEVICE NOT READY` "†ICSNED‚;;NON EXISTENT DEVICEj †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;Ä †ICDNOZ…ICDNO„IOCB„ZICBÎ &†ICBLLZ…ICBLL„IOCB„ZICB;;BUF LENØ †ICBLHZ…ICBLH„IOCB„ZICBâ '†ICBALZ…ICBAL„IOCB„ZICB;;BUF ADDRì †ICBAHZ…ICBAH„IOCB„ZICBö †ICCOMZ…ICCOM„IOCB„ZICB +†ICPUTZ…ICPUT„IOCB„ZICB;;PUT RTN ADDR &†ICAX1Z†ICAUX1„IOCB„ZICB;; 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 SERIAL I/O DEVICESP -X; SUCH AS THE DISK DRIVE(S) FROM RESIDENTZ X; HANDLERS SUCH AS FMS.d X;n ƒDCBx †DCBSBI ;;SERIAL BUS 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 !;;Format Diskette ($21) *ˆDCBCFMFM ";;Format MFM diskette ($22) X;" X; *** SPECIAL NOTE:, /X; DCBCWS may be changed to 'P ($50)6 -X; if desired to have disk DISABLE@ 2X; the verifying read after each write.J -X; Disk 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Ž ZERO PAGEAÖ X;à (X; Device drivers in general--and FMSê ,X; in particular--are allocated seven (7)ô #X; temporary bytes in zero page.þ X; (X; A device can NOT assume that these 'X; bytes will survive intact between +X; CIO calls to the device driver!2979 ;& †FMSZPG0 X;: "…ZBUFP†ICBALZ;; BUFFER POINTERD .…ERPTR ;; HOLDS POINTER TO ERROR NUMBERN *‡VTOCPTR ;; pointer to current VTOCX 0„ZSBA ;; pointer to current sector bufferb 4†CURFCB ;; CURrent FCB number ($10,$20, etc.)l X;v X; other uses of ERPTR€ X;Š &†ZTEMP1…ERPTR;; just a 1 byte temp” )†ZTEMP2…ERPTR;; just a 1 byte tempž †BUFPTR„ZSBA;; a better name¨ !…ZDRVA‡VTOCPTR;; the old name² X;¼ "A› Macros and Error CodesAÆ X;Ð )X; Macro for generating error returns:Ú X;ä ‡@ERROR î …ERRORø    X; X; X; ERROR CODES* X;4 (†E.DBAD­;;BAD SECTOR AT FORMAT TIME> -…E.APO¬;;ATTEMPT APPEND TO OLD TYPE FILEH …E.POT«;;POINT INVALIDR …E.FNFª;;FILE NOT FOUND\ ‡E.DFULL©;;DIRECTORY FULLf %†E.DVDC¨;;DEVICE COMMAND INVALIDp ‡E.FLOCK§;;FILE LOCKEDz …E.PDL¦;;POINT DATA LENGTH„ „E.FN¥;;FILE NAME ERRORŽ #†E.FNMM¤;;FILE NUMBER MISMATCH˜ &…E.SYS£;;FATAL SYS DATA I/O ERROR¢ …E.NSA¢;;NO SECTOR AVAIL¬ %…E.NSB¡;;NO SECTOR BUFFERS AVAIL¶ …E.DNO ;;DRIVE NO ERRORÀ …E.EOFˆ;; END OF FILE ERRORÊ $…E.NAK‹;; ??? simulated NAK ???Ô X;Þ X;è $X; the following MACRO is used toò (X; ensure entry point compatibilityü $X; with original Atari DOS 2.0sX; …@ORG    $: A³Entry 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 just first bytes of’&X; BIT zeropage and BIT absoluteœX;¦ ‡@SKIP1 ° $ºÄX;Î ‡@SKIP2 Ø ,âìX;