', #X;save#d:MDOS1.M65 MYDOS module9X; Copyright 1984, Charles Marslett, Wordmark SystemsX;(IX; Permission is granted by the author for any use whatsoever of this2HX; code, so long as this notice remains in the source code, and so<LX; long as the source to this routine, however modified or unmodified,F.X; is made available for a nominal cost.PX;ZX; DISK I/O EQUATESdX;n4DKADDR1;;SIO ADDRESS OF FIRST DISK DRIVE (D1:)x8TODK;;STATUS BYTE FOR A DATA TRANSFER TO THE DISKRDSTAT S;;SIO COMMAND EQUATE FOR READING THE DRIVE STATUSFWRITEV W;;SIO COMMAND EQUATE FOR WRITING A DISK WITH VERIFICATION/FMTCMD !;;SIO COMMAND TO FORMAT A DISKETTEX;.LK128};;LOCATION OF 128 BYTE SECTOR LINK.LK256;;LOCATION OF 256 BYTE SECTOR LINKX;X; ZERO PAGE EQUATESX; WARMST DOSVEC  DOSINI "X;, 6 ICHIDZ@ ICDNOZJ ICCOMZT ICSTAZ^ ICBALZh ICBAHZr ICPTLZ| ICBLLZ ICBLHZ ICAX1Z ICAX2Z CURFCB DATBYTX; CHKSUM1 BUFR2X;C FMSZPGDIRDSPFMSZPGDIRSECFMSZPG CURFNO FMSBPT& TMP10 TMP2:X;D.X; DEFINITIONS FOR THE ATARI ROM EXECUTIVENX;XDSKTIMFbRUNADRlINIADRvMEMTOPDVSTATX;$X; SIO COMMAND BUFFER DEFINITIONX; DDEVIC DUNIT DCOMND DSTATS DBUFLO DBUFHI DTIMLO DBYTLO DBYTHI  DAUX1 DAUX2 X;*X; I/O SYSTEM DEFINITIONS4X;>1HATABS;;BASE OF THE DYNAMIC HANDLER TABLEHX;R8X; CIO COMMAND TABLE BASE DEFINITIONS (FOR IOCB $00)\X;f@p ICHIDz ICDNO ICCOM ICSTA ICBAL ICBAH ICPTL ICPTH ICBLL ICBLH ICAX1 ICAX2 ICSPRX;&X; CARTRIDGE SUBSYSTEM DEFINITIONSX;(CARINIT;;LOCATION OF INIT VECTOR"CARTEST;;LOCATION OF FLAGS$&CARRUN;;LOCATION OF RUN VECTOR.X;8X; 800XL MAP CONTROLBX;LMAPREGVX;`!X; OTHER I/O PORT DEFINITIONSjX;t NMIEN~X;X; ROM VECTORSX;(DSKINVS;;OLD DISK I/O ENTRY POINT$SIOVY;;SERIAL I/O ENTRY POINTX;X; DOS BOOTING CODEX;X;X; DISK BOOT SECTORS (3)X;;;DOS.BOOT LOADS AT 0700#BOOTFL AMA;;indicate new MYDOS+BOOTL ;;NUMBER OF SECTORS IN THE BOOT /BOOTAD BOOTFL;;ADDRESS OF BOOT CODE IN RAMBOOTIN INIT*!INBOOT;;JUMP TO THE BOOT CONTINUATION(6FILES ;;NUMBER OF FILES THAT MAY BE OPEN AT ONCE23X;DRIVES = * ;USED TO BE BIT PATTERN FOR DRIVES<RAMDKU  ;;RAM DISK UNIT #F-X;BUFALC = * ;USED TO BE BUF. ALLOC. DIR.P#DEFAULT ;;DEFAULT UNIT NUMBERZ:DOSEND BOOTND;;ADDRESS OF THE FIRST BYTE OF FREE MEM.d2SECDAT ;;1=128 BYTE SECTOR/2=256 BYTE SECTORn(DOSLOC ;;SECTOR ADDRESS OF DOS.SYSx1DLINK LK128;;OFFSET TO THE SECTOR LINK FIELD-DOSAD BASE;;ADDRESS TO LOAD DOS.SYS INTOX;8INBOOT%DOSAD;;SET UP START OF DOS AS BUFFER ADDRESS QDOSAD$ BTSET;;LOW ADDR IN Y, HIGH IN AX;QDOSLOC,%DOSLOC;;PUT DOS DISK ADDRESS INTO (A,Y)X;X; DOS.SYS INPUT LOOPX;"INITLP,;;CLEAR CY, 'DO A READ'%$SECDAT;;GET CODE FOR SECTOR SIZE$FNODOS;;IF ZERO, NO DOS ON DISK!" DKIO;;INVOKE DISK I/O ROUTINE,GNODOS;;IF AN ERROR, RETURN NO-DOS ERROR"%DLINK;;POINT TO LINK,,Q@FMSZPG7;;CHECK FOR NEXT LINK (10-BITS)6ANDCDM>;;BEING ZERO,@ 5;;SAVE UPPER BYTE OF ADDRESSJ3T)L@FMSZPG7;;IF SO, LOADING IS COMPLETE^ FBOOTXTh4Q@FMSZPG7;;ELSE, IT'S THE ADDRESS OF NEXT SECTORr5;;SAVE LOWER BYTE ON STACK|2 MVBUFR;;THEN ADJUST THE BUFFER POINTER IN DCB7!?;;RESTORE LOWER BYTE TO Y-REG(7;;RECOVER UPPER BYTE OF DISK ADDRESS!DINITLP;;AND CONTINUE LOADINGX;)NODOSQ>;;NO BOOT PROGRAM ERROR CODE ;;SKIP SINGLE BYTE (LDY #)X; BOOTXT73DOSXITT?;;SET CARRY, CONVER CODE TO FINAL VALUE?;;PUT CODE INTO Y-REG:;;AND EXITX;4X; MOVE BUFFER POINTERS TO NEXT AREA TO BE LOADEDX;MVBUFRQDLINK&,04OFMSZPG;;ADD DLINK TO THE CURRENT BUFFER ADDRESS:?;;LOW BYTE TO Y-REGDQFMSZPGNO>XBTSET'FMSZPGbPFMSZPGl+BUFSET'DBUFLO;;STORE LOW BYTE INTO DCBvPDBUFHI;;THEN UPPER BYTE:X;-X; PERFORM DISK READ(CY=0) OR WRITE (CY=1)X;3DKIOPDAUX2;;STORE UPPER BYTE OF SECTOR ADDRESS'DAUX1;;THEN LOWER BYTE DKIO2%> Q>READ#DSETRTY;;IF CY=0, READ INTO RAM QWRCMDBX;%SETRTY'TMP1;;SET NUMBER OF TRIESDKFMEPDCOMND, (Q>WRITE;;CLC AND CONSTANT FOR POKERSWRCMDB   'DTIMLO*&Q>;;ASSUME A 128-BYTE SECTOR SIZE40> FSTBUFLH$DAUX2;;SECTOR > 256?R HSET256\ $DAUX1f(>;;SECTOR > 3pDSTBUFL;;IF NOTz)SET256T?;;MAKE A 256 BYTE SECTOR SIZESTBUFLPDBYTLOU? PDBYTHI+%>DKADDR;;PUT DISK DEVICE CODE INTO DCB 'DDEVICIORTRY"TMP1 GDIOXIT $DCOMND2A"$>FROMDK;;ASSUME DATA ==> DISKM>&HISREAD;;IF NOT X0,X7,X8 OR XF, OK $>TODK;;ELSE, DATA ==> DISK )ISREAD&DSTATS;;RESTORE STATUS TO DCB SIOV;;DO THE I/O OPERATIONS$ 1. GIORTRY;;IF NOT OK, RETRY8 X;B 4DIOXIT$CURFCB;;ELSE, LOAD FCB OFFSET AND STATUSL 3V C` :j X;t ,X; FIXED RAM DEFINITIONS IN BOOT SECTORS:~ X; ,DIUNIT;;UNIT NO. OF CURRECT DIRECTORY .CDIREC;;SECTOR NO. OF CURRECT DIRECTORY HOLFN 5STATE p;;DUP loaded, MEM.SAV inactive, Warmstart X; bit 7 -- MEM.SAV in use X; bit 6 -- DUP.SYS loaded &X; bit 5 -- AUTORUN.SYS already run #X; bit 4 -- Initial BUILD active X; "STKPSV;;SAVED STACK POINTER X; ;;MUST MATCH DUP LOCATION X; 2TRACKS #=(=P=M;;TRACKS IN EACH DISK FORMAT X; 5SECSIZ =======;;BUFFER SIZE TABLE( X;2 %DRVDEF R=R;;DRIVE CONFIG TABLE:<  =;;BIT 7=1 => NO DRIVEF % =;;BIT 6=1 => ATARI 810 DRIVEP / =;;BITS 5-4 IS TRACKS (SEE ABOVE TABLE)Z X; BIT 3=1 => DOUBLE DENSITYd "X; BITS 2-1 ARE DRIVE STRP RATEn X; BIT 0=1 => DOUBLE SIDEDx X; X; DOS.SYS PROGRAM FOLLOWS X; DKEPT DKOPEN  DKCLOS  DKREAD  DKWRIT  DKSTAT DKXIO X;  X; X; DOS INITIALIZATION CODE X; X; 2INITQ>i;;INITIALIZE THE CURRENT DIRECTORY 6PCDIREC;; TO THE ROOT DIRECTORY OF THE BOOT DRIVE" Q>i, PCDIREC6 X;@ X; IDENTIFY DRIVE TYPESJ X;T $>^ IDRVLP&DUNITh , ZERDVS;;ASSUME THE DRIVE IS NOT PRESENTr QDRVDEF9| 6GNXTDRV;;IF IT IS NOT DECLARED, WAIT FOR AN ACCESS ! JSTRD;;ELSE READ IT'S STATUS *FNXTDRV;;IF ABSENT, GO TO THE NEXT ONE %> WOTCPYQWOTDCB8 PDDEVIC8 1 IWOTCPY QDRVDEF9 R>@ *ENXTDRV;;IF NOT CONFIGURABLE, CONTINUE %SECSIZ9 1 SETDRV;;ELSE, TELL IT ABOUT MY CONFIGURATION X; &NXTDRV0;;STEP TO NEXT DRIVE NUMBER "HIDRVLP;;IF MORE, LOOK AT THEM X;& X; ZERO INITIALIZED MEMORY0 X;: INITPT2%>MAPBUFCHGMAPD A;;NOTE X=0 HEREN ZERLP1PCHGMAP8X 1b HZERLP1l #MAP2MODv X; )X; DEFINE TOP OF FMS FOR USER PROGRAM X; QDOSEND PMEMTOP %DOSEND X; #X; ALLOCATE FILE SECTOR BUFFERS X; !$>;;MAX OF 16 SECTOR BUFFERS &DKBFLP(FILES;;EMPTY BUFFERS DONE? DALCBUF "BUFFLG9 GDKBFSQ ALCBUFC PSBTABU9 3 DKBFSQ0;;BUMP BUFFER COUNTER* $IDKBFLP;;IF NOT CONTINUE LOOPING4 )'MEMTOP;;DEFINE TOP OF MEMORY USED> X;H X; SET UP HANDLER VECTORR X;\ FNDHND2f 2p 2z *QHATABS9;;END OF THE HANDLER TABLE? !FNOHAND;;THEN INSTALL IT HERE R>D;;A 'D' ALREADY PRESENT? !HFNDHND;;NO, CONTINUE LOOKING X; 1NOHANDQ>D;;END OF TABLE OR CURRENT 'D' ENTRY PHATABS9 (Q>DKEPT;;STASH MYDOS ENTRY VECTOR PHATABS9 Q>DKEPT "PHATABS9;;BUILD HANDLER VECTOR B!;;DUPINV (dup code modifies this) ;DONE, INITIALIZE DUP CODE X; X;'X; DOS NON-ZERO PAGE RAM ALLOCATIONSX; CHGMAP$ CURMAP. MAP28MAP2MODB LSTSECLLSTIOCBVX;`=X; MYDOS FCB STRUCTURE (ALMOST THE SAME AS ATARI DOS 2.0)jX;t FCBFNO~FCBOTC;;OPEN TYPE CODE FCBFLG MAXLEN CURLEN BUFNO CURSEC LNKSEC SECCNT*DIRBAS;;BASE ADDRESS OF CUR. SECTOR SAVSEC FCBLENFCBLENX;&BUFFLG;;IF 0, BUFFER NOT IN USE 6SBTABU;;UPPER BYTE OF THE SECTOR BUFFER ADDRESS(MAPBUF;;SPACE ALLOCATED FOR VTOC7DIRBUFMAPBUF;;SPACE ALLOCATED TO READ DIRECTORIES( FNAME 2 CURMP<X;FX;P BASE Z/HDTAB ===;;8 LOGICAL HARD DRIVES OFd) ===;;UP TO 65535 SECTORS EACHnX;xBX;this table is referenced by DUP.SYS, and should not be moved!X;X;X; DOS CONFIGURATION CODEX;X;=X; CONTROL BLOCK TO BE WRITTEN TO A DRIVE TO CONFIGURE ITX;WOTDCB N=@ DIRBUF=  =X;PX; THE CONFIGURATION CODE, FORCES A DRIVE INTO THE APPROPRIATE CONFIGURATIONX;"SETDRVM>?;;EXTRACT CONF. BITS PTMP1 'TMP2"% SIOV;;READ CURRENT CONFIGURATION, GJSTRD6 QTMP1@ %TMP2JV?T5;;SAVE REMAINING BITS^M>;;EXTRACT STEP RATE CODEhPDIRBUFrQ>|PDIRBUFU?'PDIRBUF;;STORE DOUBLE SIDED FLAGC;;GET DENSITYV?/PDIRBUF;;STORE UPPER BYTE OF SECTOR SIZEW?PDIRBUF;;THEN LOWER BYTEU?T?T?PDIRBUF7V?V?!V?;;POSITION TRACK COUNT FIELD?&"QTRACKS8;;GET NUMBER OF TRACKS0 PDIRBUF:M>;;SEE IF 77 TRACK 8 IN.D5NV?X/LDIRBUF;;MERGE D/DENSITY WITH 8 IN. FLAGbPDIRBUFl7vT?;;CONVERT TO 0 OR 8 O>;;SECTOR COUNT = 18 OR 26PDIRBUF %DUNITQHDTAB8 FTOSIOV!PDIRBUF;;SIZE = SECTORS/TKQHDTAB8 PDIRBUF;;LOW BYTE OF SIZEQ>PDIRBUF;;ONE TRACK/DRIVE+TOSIOV#DCOMND;;CHANGE COMMAND TO WRITEQ>"PDSTATS;;SET DIRECTION -> DISK& SIOV;;WRITE OPTION TABLE TO DRIVE X;FX; AND THIS ROUTINE MAKES SURE IT REALLY DID HAPPEN AS WE THOUGHT! X;*JSTRDQ>RDSTAT4 PDCOMND> DSKINVH $DUNITRC\ GZERDVSf QDVSTATpT?;;SECTOR SIZE=256?zT?T?Q>O>SETSIZPSECSIZ9:X;ZERDVSQ>FSETSIZ;;branch alwaysX;X; DOS RAMDISK CODEX;X;+X; RAM DISK I/O HANDLER (POS. IND. CODE)X; MAPAGE ===$ ===. ===8 ===BX;L ===V ===` ===j ===tX;~ === === ===Ϝ ===X; === === === ===X; VALSEC5CL>V?  PBUFR=;;DISABLE INT-SQ>(PNMIEN;;DISABLE NMI-S2W?< PBUFRF7P?Z QMAPREGdL>n PCHKSUMxL>| MMAPAGE8%PMAPREG;;SELECT RAMDISK DATA PAGEX;*QDBUFLO;;USER BUFFER ADDRESS GOES HERE PBUFRQDBUFLO PBUFR%>8DRREADL;;CY=0 IF READRWRITLQ@BUFR7 P@BUFR73 IRWRITL GRIOXX;")RDKIO'DAUX1;;*** FOR FORMAT CODE ***,)>6U?@R>J/RDKLMT ;;NUMBER OF 16K PAGES IN RAMDISKT!DVALSEC;;CALCULATE MEM. ADDR.^8hQ>r GRERROR|X;RREADLQ@BUFR7P@BUFR73 IRREADLX;%RIOXQCHKSUM;;FORCE REAL RAM PAGEPMAPREG;;BEFORE EXITINGQ>PNMIEN;;RE-ENABLE NMI.;;ENABLE INTERRUPTSQ>;;RETURN '1' IN Y-REG&RERRORPDSTATS;;AND IN STATUS BYTE$CURFCB;;RESTORE FCB ADDR?:;;THEN EXIT