     1                                  ;       SCCSID = @(#)rom.asm    1.1 85/04/10
     2                                  ;TITLE   ROM - Miscellaneous routines
     3                                  ;NAME    ROM
     4                                  ; Misc Low level routines for doing simple FCB computations, Cache
     5                                  ;       reads and writes, I/O optimization, and FAT allocation/deallocation
     6                                  ;
     7                                  ;   SKPCLP
     8                                  ;   FNDCLUS
     9                                  ;   BUFSEC
    10                                  ;   BUFRD
    11                                  ;   BUFWRT
    12                                  ;   NEXTSEC
    13                                  ;   OPTIMIZE
    14                                  ;   FIGREC
    15                                  ;   ALLOCATE
    16                                  ;   RESTFATBYT
    17                                  ;   RELEASE
    18                                  ;   RELBLKS
    19                                  ;   GETEOF
    20                                  ;
    21                                  ;   Modification history:
    22                                  ;
    23                                  ;       Created: ARR 30 March 1983
    24                                  ;
    25                                  
    26                                  ;
    27                                  ; get the appropriate segment definitions
    28                                  ;
    29                                  [list -]
    29          ******************       warning: redefining multi-line macro `struc' [-w+pp-macro-redef-multi]
    14                              <4> [list -]
    14          ******************  <4>  warning: redefining multi-line macro `__@@_next' [-w+pp-macro-redef-multi]
    14                              <3> [list -]
     3                              <2> 
     4                              <2> addsection DOSSTART, align=16 PUBLIC class=DOSSTART
     5                              <2> ; (no prior section) ; DOSSTART		ENDS
     6                              <2> 
     7                              <2> addsection DOSSTARTJUMP, align=1 PUBLIC class=START
     8                              <2> ; (no prior section) ; DOSSTARTJUMP		ENDS
     9                              <2> 
    10                              <2> addsection CONSTANTS, align=2 PUBLIC class=CONST
    11                              <2> ; (no prior section) ; CONSTANTS	ENDS
    12                              <2> 
    13                              <2> addsection DATA, align=2 PUBLIC class=DATA
    14                              <2> ; (no prior section) ; DATA		ENDS
    15                              <2> 
    16                              <2> addsection TABLE, align=2 PUBLIC class=TABLE
    17                              <2> ; (no prior section) ; TABLE		ENDS
    18                              <2> 
    19                              <2> addsection DOSDATATABLE, align=2 PUBLIC class=DOSDATACODE
    20                              <2> ; (no prior section) ; DOSDATATABLE		ENDS
    21                              <2> 
    22                              <2> addsection DOSDATACODE, align=1 PUBLIC class=DOSDATACODE
    23                              <2> ; (no prior section) ; DOSDATACODE		ENDS
    24                              <2> 
    25                              <2> addsection DOSBIODATA, align=2 PUBLIC class=DOSBIODATA
    26                              <2> 
    27                              <2> addsection LAST, align=16 PUBLIC class=LAST
    28                              <2> ; (no prior section) ; LAST		ENDS
    29                              <2> 
    30                              <2> group DOSGROUP DOSSTART DOSSTARTJUMP CONSTANTS DATA TABLE DOSDATATABLE DOSDATACODE DOSBIODATA LAST
     8                              <1> 
     9                              <1> %include "dcodeseg.nas"
     1                              <2> 
     2                              <2> %ifndef DCODESEGNAS
     3                              <2> %assign DCODESEGNAS 1
     4                              <2> 
     5                              <2> section DOSCODETABLE align=2 PUBLIC class=DOSCODE
     6                              <2> ; (no prior section) ; DOSCODETABLE		ENDS
     7                              <2> section DOSCODECODE align=1 PUBLIC class=DOSCODE
     8                              <2> ; (no prior section) ; DOSCODECODE		ENDS
     9                              <2> section DOSBIOCODE align=2 PUBLIC class=DOSCODE
    10                              <2> section BIOCODE	align=2 PUBLIC class=DOSCODE
    11                              <2> 
    12                              <2> %ifnidni DOSENTRYGROUP, DOSCODEGROUP
    13                              <2>  group DOSCODEGROUP DOSCODETABLE DOSCODECODE DOSBIOCODE BIOCODE
    14                              <2> %endif
    15                              <2> 
    16                              <2> %endif
    10                              <1> 
    11                              <1> section LAST
    12                              <1> ; (no prior section) ; LAST		ENDS
    32                                  %include "fastseek.mac"			       ; DOS 4.00
     1                              <1> ;
     2                              <1> ;Equates for FASTSEEK.
     3                              <1> ;
     4                              <1> ;FASTSEEK flags
     5                              <1> ;
     6                              <1> FS_begin      equ    00000001B
     7                              <1> FS_end	      equ    11111110B
     8                              <1> FS_insert     equ    00000010B
     9                              <1> FS_no_insert  equ    11111101B
    10                              <1> 
    11                              <1> ;FASTSEEK EXTENT CACHING Subfunctions
    12                              <1> FSEC_open	equ	11
    13                              <1> FSEC_close	equ	12
    14                              <1> FSEC_delete	equ	13
    15                              <1> FSEC_lookup	equ	14
    16                              <1> FSEC_insert	equ	15
    17                              <1> FSEC_truncate	equ	16
    18                              <1> ;
    19                              <1> ;Equates used in DOS.
    20                              <1> 
    21                              <1> 
    22                              <1> ;
    33                                  %include "fastxxxx.mac"			       ; DOS 4.00
     1                              <1> ; Fastxxx equates
     2                              <1> FastOpen_ID	   equ	   1
     3                              <1> FastSeek_ID	   equ	   2
     4                              <1> Fast_yes	   equ	   10000000B	 ; fastxxx flag
     5                              <1> 
     6                              <1> ;Structure definitions
     7                              <1> ;
     8                              <1> Fasttable_Entry  struc			 ; Fastxxx  Entry pointer in DOS
     9 00000000 ????                <1> Fast_Entry_Num	    dw	    ?		 ; number of entries
    10 00000002 ????????            <1> FastOpen_Seek	    dd	    ?		 ; fastopen & fastseek entry address
    11                              <1> Fasttable_Entry  ends
    12                              <1> ;
    34                                  %include "version.mac"
     1                              <1> ; Some modules really want TRUE to be 0FFH.  Best to let them have their way.
     2                              <1> 	TRUE	   EQU	   0FFFFh
     3                              <1> 	TRUEBYTE   EQU     0FFh
     4                              <1> 	FALSE	   EQU	   0
     5                              <1> 
     6                              <1> ;
     7                              <1> ; Use the following switches to control cmacros.inc
     8                              <1> ;
     9                              <1> ?PLM       equ       0
    10                              <1> ?WIN       equ       0
    11                              <1> 
    12                              <1> memS       EQU     1			; Small model
    13                              <1> ;
    14                              <1> ; Use the switches below to produce the standard Microsoft version or the IBM
    15                              <1> ; version of the operating system
    16                              <1> ;
    17                              <1> ; The below chart will indicate how to set the switches to build the various
    18                              <1> ; versions
    19                              <1> ;
    20                              <1> ;                     IBMVER          IBMCOPYRIGHT
    21                              <1> ; --------------------------------------------------------
    22                              <1> ;  IBM Version   |     TRUE              TRUE
    23                              <1> ; --------------------------------------------------------
    24                              <1> ;  MS Version    |     FALSE             FALSE
    25                              <1> ; --------------------------------------------------------
    26                              <1> ;  Clone Version |     TRUE              FALSE
    27                              <1> ;
    28                              <1> IBMVER     EQU     TRUE
    29                              <1> IBMCOPYRIGHT EQU   FALSE
    30                              <1> 
    31                              <1> BUFFERFLAG	EQU	~ IBMCOPYRIGHT
    32                              <1> 
    33                              <1> %ifndef	MSVER	
    34                              <1> MSVER      EQU     ~ IBMVER
    35                              <1> %endif
    36                              <1> IBM	   EQU	   IBMVER
    37                              <1> ;
    38                              <1> ;
    39                              <1> 	%IF IBMVER
    40                              <1> 	    %IF IBMCOPYRIGHT
    41                              <1>               %warning out: ... IBM version build switch on ...
    42                              <1> 	    %ELSE
    43                              <1> 	      %warning out: ... CLONE version build switch on ...
    43          ******************  <1>  warning: out: ... CLONE version build switch on ... [-w+user]
    44                              <1> 	    %ENDIF
    45                              <1> 	%ELSE
    46                              <1> 	    %IFN IBMCOPYRIGHT
    47                              <1> 	      %warning out: ... MS version build switch on ...
    48                              <1> 	    %ELSE
    49                              <1> 	      %warning out: !!!!!!!!!  VERSION SWITCHES SET INCORECTLY  !!!!!!!!!
    50                              <1> 	      %warning out: !!!!!!!!! CHECK SETTINGS IN INC\VERSION.INC !!!!!!!!!
    51                              <1> 	    %ENDIF
    52                              <1> 	%ENDIF   
    53                              <1> ;
    54                              <1> ;
    55                              <1> ;***************************************************************************
    56                              <1> ;*          The following switches are for DBCS or SBCS support            *
    57                              <1> ;*                                                                         *
    58                              <1> ;*                     Set INTERNAT EQU TRUE FOR DBCS                      *
    59                              <1> ;*                     Set INTERNAT EQU FALSE FOR SBCS                     *
    60                              <1> ;*                                                                         *
    61                              <1> ;***************************************************************************
    62                              <1> ;
    63                              <1> IBMJAPVER  EQU	   FALSE		;If TRUE set KANJI true also
    64                              <1> 
    65                              <1> ;
    66                              <1> ; Switch INTERNAT for DBCS support
    67                              <1> ;
    68                              <1> INTERNAT   EQU	   FALSE
    69                              <1> ;
    70                              <1> 	%IF INTERNAT
    71                              <1> %ifndef KANJI
    72                              <1> KANJI	   EQU	   TRUE
    73                              <1> %endif
    74                              <1> IBMJAPAN   EQU	   TRUE
    75                              <1> 	%ELSE
    76                              <1> %ifndef KANJI
    77                              <1> KANJI	   EQU	   FALSE
    78                              <1> %endif
    79                              <1> IBMJAPAN   EQU	   FALSE
    80                              <1> 	%ENDIF
    81                              <1> 
    82                              <1> %ifndef altvect				; avoid jerking off vector.inc
    83                              <1> ALTVECT    EQU	   FALSE		;Switch to build ALTVECT version
    84                              <1> %endif
    85                              <1> 
    86                              <1> ;
    87                              <1> ; Country code switches
    88                              <1> ; The default contry code is assumed as USA.
    89                              <1> ;
    90                              <1> 	%IF INTERNAT
    91                              <1>  KOREA	   EQU	   TRUE
    92                              <1>  JAPAN	   EQU	   FALSE
    93                              <1> 	%ELSE
    94                              <1>  KOREA	   EQU	   FALSE
    95                              <1>  JAPAN	   EQU	   FALSE
    96                              <1> 	%ENDIF
    97                              <1> ;
    98                              <1> 		%IF INTERNAT
    99                              <1> %warning out: Internat(ECS) version build switch on
   100                              <1> 		%ENDIF
    35                                  
    36                                  [list +]
    37                                  section DOSCODECODE
    38                                  [list -]
    38          ******************       warning: out: ... for DOS Version 4.00 ... [-w+user]
    38          ******************       warning: out: BPB.INC... [-w+user]
    38          ******************       warning: out: ... CLONE version build switch on ... [-w+user]
    38          ******************       warning: out: DEVSYM.INC... [-w+user]
    46                                  
    47                                          i_need  CLUSNUM,WORD
    48                                          i_need  NEXTADD,WORD
    49                                          i_need  LASTPOS,WORD
    50                                          i_need  SECCLUSPOS,BYTE
    51                                          i_need  FATBYT,WORD
    52                                          i_need  THISSFT,DWORD
    53                                          i_need  TRANS,BYTE
    54                                          i_need  BYTCNT1,WORD
    55                                          i_need  CURBUF,DWORD
    56                                          i_need  BYTSECPOS,WORD
    57                                          i_need  DMAADD,WORD
    58                                          i_need  SECPOS,DWORD                         ;F.C. >32mb
    59                                          i_need  VALSEC,DWORD                         ;F.C. >32mb
    60                                          i_need  ALLOWED,BYTE
    61                                          i_need  FSeek_drive,BYTE                     ; DOS 3.4
    62                                          i_need  FSeek_firclus,WORD                   ; DOS 3.4
    63                                          i_need  FSeek_logclus,WORD                   ; DOS 3.4
    64                                          i_need  FSeek_logsave,WORD                   ; DOS 3.4
    65                                          i_need  FastSeekFlg,BYTE                     ; DOS 3.4
    66                                          i_need  XA_condition,BYTE                    ; DOS 3.4
    67                                          i_need  HIGH_SECTOR,WORD                     ; DOS 3.4
    68                                          i_need  DISK_FULL,BYTE                       ; DOS 3.4
    69                                          i_need  Temp_VAR2,WORD                       ; DOS 3.4
    70                                  	i_need	Cluster_Next_EDR,WORD
    71                                  
    72                                  
    73                                   assume nocheck, ss:DOSGROUP
    74                                  
    75                                  Break   <FNDCLUS -- Skip over allocation units>
    76                                  
    77                                  ; Inputs:
    78                                  ;       CX = No. of clusters to skip
    79                                  ;       ES:BP = Base of drive parameters
    80                                  ;       [THISSFT] point to SFT
    81                                  ; Outputs:
    82                                  ;       BX = Last cluster skipped to
    83                                  ;       CX = No. of clusters remaining (0 unless EOF)
    84                                  ;       DX = Position of last cluster
    85                                  ;       Carry set if error (currently user FAILed to I 24)
    86                                  ; DI destroyed. No other registers affected.
    87                                  
    88                                          procedure   FNDCLUS,NEAR
    88          ******************       warning: proc FNDCLUS... [-w+user]
    89                                          DOSAssume   CS,<DS>,"FndClus"
    90                                          ASSUME  ES:NOTHING
    91                                  
    92                                          Assert      ISDPB,<ES,BP>,"FndCLus"
    93                                  ;; 10/31/86 FastSeek
    94 00000000 06                              PUSH    ES
    95 00000001 C43E[0000]                      LES     DI,[THISSFT]
    96                                          Assert      ISSFT,<ES,DI>,"FndClus"
    97 00000005 890E[0000]                      MOV     [FSeek_logclus],CX                ; presume CX is the position  ;AN000;
    98 00000009 268B5D35                        MOV     BX,[ES:DI + sf_lstclus]
    99 0000000D 268B5519                        MOV     DX,[ES:DI + sf_cluspos]
   100                                  ;; 10/31/86 FastSeek
   101 00000011 85DB                            test    BX,BX
   102 00000013 7503                            JNZ     YCLUS
   103 00000015 E9A000                          JMP     NOCLUS
   104                                  YCLUS:
   105 00000018 29D1                            SUB     CX,DX
   106 0000001A 7308                            JNB     FINDIT
   107 0000001C 01D1                            ADD     CX,DX
   108 0000001E 31D2                            XOR     DX,DX
   109 00000020 268B5D0B                        MOV     BX,[ES:DI + sf_firclus]
   110                                  FINDIT:
   111                                  ;; 10/31/86 FastSeek
   112                                  
   113                                  
   114 00000024 07                              POP     ES
   115                                   assume es:DPB
   116 00000025 85C9                            test    CX,CX
   117                                  skpclp equ SKPCLP	; NASM port label
   118 00000027 7503                            JNZ     skpclp
   119 00000029 E98500                          JMP     RET10
   120                                  
   121                                  entry   SKPCLP
   122                                  FastSeekflg equ FastSeekFlg	; NASM port label
   123 0000002C F606[0000]80                    TEST    byte [FastSeekflg],Fast_yes            ; fastseek installed?         ;AN000;
   124 00000031 745E                            JZ      dos_do_norm                           ; no                          ;AN000;
   125 00000033 F606[0000]01                    TEST    byte [FastSeekflg],FS_begin            ; do fastseek                 ;AN000;
   126 00000038 7457                            JZ      dos_do_norm                           ; no                          ;AN000;
   127 0000003A F606[0000]02                    TEST    byte [FastSeekflg],FS_insert           ; is in insert mode ?         ;AN000;
   128 0000003F 7550                            JNZ     dos_do_norm                           ; yes                         ;AN000;
   129                                  Temp_Var2 equ Temp_VAR2	; NASM port label
   130 00000041 891E[0000]                      MOV     [Temp_Var2],BX                    ; save physical cluster       ;AN000;
   131                                                                                    ; PTR P005079
   132                                  SKPCLP2:
   133 00000045 E8(0000)                        invoke  FastSeek_Lookup                   ; ask for next cluster #      ;AN000;
   134 00000048 7373                            JNC     clusfound                         ; yes, we got it              ;AN000;
   135 0000004A 83FF01                          CMP     DI,1                              ; valid drive ,e.g. C,D...    ;AN000;
   136 0000004D 7507                            JNZ     par_found                         ; yes,                        ;AN000;
   137 0000004F 8026[0000]80                    AND     byte [FastSeekflg],Fast_yes            ; no more, fastseek           ;AN000;
   138 00000054 EB3B                            JMP     SHORT dos_do_norm                                                   ;AN000;
   139                                                                                                                  ;AN000;
   140                                  par_found:
   141                                  FS_Trunc_EOF equ FS_TRUNC_EOF	; NASM port label
   142 00000056 E8A403                          CALL    FS_Trunc_EOF                      ; check EOF and truncate      ;AN000;
   143 00000059 73EA                            JNC     SKPCLP2                           ; redo lookup                 ;AN000;
   144                                  noteof:
   145 0000005B 800E[0000]02                    OR      byte [FastSeekflg],FS_insert           ; no, start to insert         ;AN000;
   146 00000060 3B16[0000]                      CMP     DX,[FSeek_logsave]                ; is current better than new? ;AN000;
   147 00000064 7613                            JBE     OnCache                           ; no, let's use new           ;AN000;
   148 00000066 8916[0000]                      MOV     [FSeek_logclus],DX                ; use current                 ;AN000;
   149 0000006A 8B1E[0000]                      MOV     BX,[Temp_Var2]                    ; retore pysical cluster      ;AN000;
   150 0000006E 89DF                            MOV     DI,BX                             ; insert cureent cluster      ;AN000;
   151 00000070 E8(0000)                        invoke  FastSeek_Insert                   ; insert cluster # to         ;AN000;
   152 00000073 FF06[0000]                      INC     word [FSeek_logclus]                   ; get next inserted position  ;AN000;
   153 00000077 EB18                            JMP     SHORT dos_do_norm
   154                                  OnCache:
   155 00000079 8B0E[0000]                      MOV     CX,[FSeek_logclus]                ; get the number of clusters  ;AN000;
   156 0000007D 2B0E[0000]                      SUB     CX,[FSeek_logsave]                ; we need to skip             ;AN000;
   157 00000081 8B16[0000]                      MOV     DX,[FSeek_logsave]                ; cluster position            ;AN000;
   158                                  dodo:
   159 00000085 FF06[0000]                      INC     word [FSeek_logsave]                   ; get next inserted position  ;AN000;
   160 00000089 FF36[0000]                      PUSH    word [FSeek_logsave]                   ; logclus=logsave             ;AN000;
   161 0000008D 8F06[0000]                      POP     word [FSeek_logclus]                                                 ;AN000;
   162                                  
   163                                  dos_do_norm:
   164                                  
   165 00000091 E8(0000)                        invoke  UNPACK
   166 00000094 7301C3                          retc
   167                                  
   168 00000097 E8(0000)                        invoke  FastSeek_Insert                   ; insert cluster # to         ;AN000;
   169                                  cluss:                                                                          ;AN000;
   170 0000009A 53                              PUSH    BX                                ; FastSeek                    ;AN000;
   171 0000009B 89FB                            MOV     BX,DI
   172 0000009D E8(0000)                        Invoke  IsEOF
   173 000000A0 5B                              POP     BX
   174 000000A1 730E                            JAE     RET10
   175 000000A3 87DF                            XCHG    BX,DI
   176 000000A5 42                              INC     DX
   177 000000A6 FF06[0000]                      INC     word [FSeek_logclus]                  ; increment for next inserted  ;AN000;
   178 000000AA E202                            LOOP    SKPCLPX
   179 000000AC EB03                            JMP     short  RET10
   180                                  SKPCLPX:
   181 000000AE E97BFF                          JMP     SKPCLP
   182                                  RET10:                                                                          ;AN000;
   183 000000B1 8026[0000]FD                    AND     byte [FastSeekflg],FS_no_insert       ; clear insert mode
   184 000000B6 F8                              CLC
   185 000000B7 C3                              return
   186                                  NOCLUS:
   187 000000B8 07                              POP     ES
   188                                   assume es:nothing
   189 000000B9 41                              INC     CX
   190 000000BA 4A                              DEC     DX
   191 000000BB F8                              CLC
   192 000000BC C3                              return
   193                                  clusfound:
   194 000000BD 8B16[0000]                      MOV     DX,[FSeek_logclus]                ; get cluster position        ;AN000;
   195 000000C1 8B1E[0000]                      MOV     BX,[FSeek_logsave]                ; bx=previous cluster # PTM   ;AN000;
   196 000000C5 4A                              DEC     DX                                                              ;AN000;
   197 000000C6 B90100                          MOV     CX,1                              ; we found it                 ;AN000;
   198 000000C9 EBCF                            JMP     cluss                                                           ;AN000;
   199                                  
   200                                  EndProc FNDCLUS
   201                                  
   202                                  Break  <BUFSEC -- BUFFER A SECTOR AND SET UP A TRANSFER>
   203                                  
   204                                  ; Inputs:
   205                                  ;       AH = priority of buffer
   206                                  ;       AL = 0 if buffer must be read, 1 if no pre-read needed
   207                                  ;       ES:BP = Base of drive parameters
   208                                  ;       [CLUSNUM] = Physical cluster number
   209                                  ;       [SECCLUSPOS] = Sector position of transfer within cluster
   210                                  ;       [BYTCNT1] = Size of transfer
   211                                  ; Function:
   212                                  ;       Insure specified sector is in buffer, flushing buffer before
   213                                  ;       read if necessary.
   214                                  ; Outputs:
   215                                  ;       ES:DI = Pointer to buffer
   216                                  ;       SI = Pointer to transfer address
   217                                  ;       CX = Number of bytes
   218                                  ;       [NEXTADD] updated
   219                                  ;       [TRANS] set to indicate a transfer will occur
   220                                  ;       Carry set if error (user FAILed to I 24)
   221                                  
   222                                          procedure   BUFSEC,NEAR
   222          ******************       warning: proc BUFSEC... [-w+user]
   223                                          DOSAssume   CS,<DS>,"BufSec"
   224                                          ASSUME  ES:NOTHING
   225                                  
   226                                          Assert      ISDPB,<ES,BP>,"BufSec"
   227 000000CB 8B16[0000]                      MOV     DX,[CLUSNUM]
   228 000000CF 8A1E[0000]                      MOV     BL,[SECCLUSPOS]
   229                                  allowed_FAIL equ Allowed_FAIL	; NASM port equate
   230                                  allowed_RETRY equ Allowed_RETRY	; NASM port equate
   231                                  allowed_IGNORE equ Allowed_IGNORE	; NASM port equate
   232 000000D3 C606[0000]38                    MOV     byte [ALLOWED],allowed_FAIL + allowed_RETRY + allowed_IGNORE
   233 000000D8 E8EA01                          CALL    FIGREC
   234 000000DB E8(0000)                        invoke  GETBUFFR
   235 000000DE 72DC                            retc
   236 000000E0 C606[0000]01                    MOV     BYTE PTR [TRANS],1      ; A transfer is taking place
   237 000000E5 8B36[0000]                      MOV     SI,[NEXTADD]
   238 000000E9 89F7                            MOV     DI,SI
   239 000000EB 8B0E[0000]                      MOV     CX,[BYTCNT1]
   240 000000EF 01CF                            ADD     DI,CX
   241 000000F1 893E[0000]                      MOV     [NEXTADD],DI
   242 000000F5 C43E[0000]                      LES     DI,[CURBUF]
   243                                          Assert  ISBUF,<ES,DI>,"BufSec"
   244 000000F9 26804D0508                      OR      byte [ES:DI + buf_flags],buf_isDATA
   245 000000FE 8D7D10                          LEA     DI,[DI + BUFINSIZ]        ; Point to buffer
   246 00000101 033E[0000]                      ADD     DI,[BYTSECPOS]
   247 00000105 F8                              CLC
   248 00000106 C3                              return
   249                                  EndProc BUFSEC
   250                                  
   251                                  Break   <BUFRD, BUFWRT -- PERFORM BUFFERED READ AND WRITE>
   252                                  
   253                                  ; Do a partial sector read via one of the system buffers
   254                                  ; ES:BP Points to DPB
   255                                  ; Carry set if error (currently user FAILed to I 24)
   256                                  
   257                                          procedure   BUFRD,NEAR
   257          ******************       warning: proc BUFRD... [-w+user]
   258                                          DOSAssume   CS,<DS>,"BufRd"
   259                                          ASSUME  ES:NOTHING
   260                                  
   261                                          Assert      ISDPB,<ES,BP>,"BufRd"
   262 00000107 06                              PUSH    ES
   263 00000108 B80000                          MOV     AX,0
   264 0000010B E8BDFF                          CALL    BUFSEC
   265 0000010E 7303                            JNC     BUF_OK
   266                                  BUF_IO_FAIL:
   267 00000110 07                              POP     ES
   268                                   assume es:nothing
   269 00000111 EB29                            JMP     SHORT RBUFPLACED
   270                                  
   271                                  BUF_OK:
   272 00000113 8CC3                            MOV     BX,ES
   273 00000115 8E06[0200]                      MOV     ES,[DMAADD+2]
   274                                   assume es:nothing
   275 00000119 8EDB                            MOV     DS,BX
   276                                  ASSUME  DS:NOTHING
   277 0000011B 87FE                            XCHG    DI,SI
   278 0000011D D1E9                            SHR     CX,1
   279 0000011F 7301                            JNC     EVENRD
   280 00000121 A4                              MOVSB
   281                                  EVENRD:
   282 00000122 F3A5                            REP     MOVSW
   283 00000124 07                              POP     ES
   284                                   assume es:DPB
   285 00000125 36C53E[0000]                    LDS     DI,[ss:CURBUF]
   286                                   assume ds:nothing
   287                                          Assert  ISBUF,<DS,DI>,"BufRD/EvenRD"
   288                                  BufInSiz equ BUFINSIZ	; NASM port equate
   289 0000012A 8D5D10                          LEA     BX,[DI + BufInSiz]
   290 0000012D 29DE                            SUB     SI,BX                   ; Position in buffer
   291 0000012F E8(0000)                        invoke  PLACEBUF
   292                                          Assert  ISDPB,<ES,BP>,"BufRD/EvenRD"
   293 00000132 263B7602                        CMP     SI,[ES:BP + dpb_sector_size] ; Read Last byte?
   294 00000136 7203                            JB      RBUFPLACEDC             ; No, leave buf where it is
   295 00000138 E8(0000)                        invoke  PLACEHEAD               ; Make it prime candidate for chucking
   296                                                                          ;  even though it is MRU.
   297                                  RBUFPLACEDC:
   298 0000013B F8                              CLC
   299                                  RBUFPLACED:
   300 0000013C 16                              PUSH    SS
   301 0000013D 1F                              POP     DS
   302                                   assume ds:DOSGROUP
   303 0000013E C3                              return
   304                                  EndProc BUFRD
   305                                  
   306                                  ; Do a partial sector write via one of the system buffers
   307                                  ; ES:BP Points to DPB
   308                                  ; Carry set if error (currently user FAILed to I 24)
   309                                  
   310                                          procedure   BUFWRT,NEAR
   310          ******************       warning: proc BUFWRT... [-w+user]
   311                                          DOSAssume   CS,<DS>,"BufWrt"
   312                                          ASSUME  ES:NOTHING
   313                                  
   314                                          Assert      ISDPB,<ES,BP>,"BufWrt"
   315 0000013F A1[0000]                        MOV     AX,WORD PTR [SECPOS]
   316 00000142 83C001                          ADD     AX,1            ; Set for next sector
   317 00000145 A3[0000]                        MOV     WORD PTR [SECPOS],AX      ;F.C. >32mb                           ;AN000;
   318 00000148 8316[0200]00                    ADC     WORD PTR [SECPOS+2],0     ;F.C. >32mb                           ;AN000;
   319 0000014D A1[0200]                        MOV     AX,WORD PTR [SECPOS+2]    ;F.C. >32mb                           ;AN000;
   320 00000150 3B06[0200]                      CMP     AX,WORD PTR [VALSEC+2]    ;F.C. >32mb                           ;AN000;
   321 00000154 B001                            MOV     AL,1                      ;F.C. >32mb                           ;AN000;
   322 00000156 770F                            JA      NOREAD                    ;F.C. >32mb                           ;AN000;
   323 00000158 720B                            JB      doread                    ;F.C. >32mb                           ;AN000;
   324 0000015A A1[0000]                        MOV     AX,WORD PTR [SECPOS]      ;F.C. >32mb                           ;AN000;
   325 0000015D 3B06[0000]                      CMP     AX,WORD PTR [VALSEC]     ; Has sector been written before?
   326 00000161 B001                            MOV     AL,1
   327 00000163 7702                            JA      NOREAD          ; Skip preread if SECPOS>VALSEC
   328                                  doread:
   329 00000165 30C0                            XOR     AL,AL
   330                                  NOREAD:
   331 00000167 06                              PUSH    ES
   332 00000168 E860FF                          CALL    BUFSEC
   333 0000016B 72A3                            JC      BUF_IO_FAIL
   334 0000016D 8E1E[0200]                      MOV     DS,[DMAADD+2]
   335                                  ASSUME  DS:NOTHING
   336 00000171 D1E9                            SHR     CX,1
   337 00000173 7301                            JNC     EVENWRT
   338 00000175 A4                              MOVSB
   339                                  EVENWRT:
   340 00000176 F3A5                            REP     MOVSW
   341 00000178 07                              POP     ES
   342                                   assume es:nothing
   343 00000179 36C51E[0000]                    LDS     BX,[ss:CURBUF]
   344                                          Assert  ISBUF,<DS,BX>,"BufWrt/EvenWrt"
   345                                  
   346 0000017E F6470540                        TEST    byte [BX + buf_flags],buf_dirty  ;LB. if already dirty                 ;AN000;
   347 00000182 7507                            JNZ     yesdirty                  ;LB.    don't increment dirty count   ;AN000;
   348 00000184 E8(0000)                        invoke  INC_DIRTY_COUNT           ;LB.                                  ;AN000;
   349 00000187 804F0540                        OR      byte [BX + buf_flags],buf_dirty
   350                                  yesdirty:
   351 0000018B 8D7710                          LEA     SI,[BX + BufInSiz]
   352 0000018E 29F7                            SUB     DI,SI                   ; Position in buffer
   353 00000190 89FE                            MOV     SI,DI
   354 00000192 89DF                            MOV     DI,BX
   355 00000194 E8(0000)                        invoke  PLACEBUF
   356                                          Assert  ISDPB,<ES,BP>,"BufWrt/EvenWrt"
   357 00000197 263B7602                        CMP     SI,[ES:BP + dpb_sector_size]  ; Written last byte?
   358 0000019B 7203                            JB      WBUFPLACED              ; No, leave buf where it is
   359 0000019D E8(0000)                        invoke  PLACEHEAD               ; Make it prime candidate for chucking
   360                                                                          ;  even though it is MRU.
   361                                  WBUFPLACED:
   362 000001A0 F8                              CLC
   363 000001A1 16                              PUSH    SS
   364 000001A2 1F                              POP     DS
   365                                   assume ds:DOSGROUP
   366 000001A3 C3                              return
   367                                  EndProc BUFWRT
   368                                  
   369                                  Break   <NEXTSEC -- Compute next sector to read or write>
   370                                  
   371                                  ; Compute the next sector to read or write
   372                                  ; ES:BP Points to DPB
   373                                  
   374                                          procedure   NEXTSEC,NEAR
   374          ******************       warning: proc NEXTSEC... [-w+user]
   375                                          DOSAssume   CS,<DS>,"NextSec"
   376                                          ASSUME  ES:NOTHING
   377                                  
   378                                          Assert      ISDPB,<ES,BP>,"NextSec"
   379 000001A4 F606[0000]FF                    TEST    BYTE PTR [TRANS],-1
   380 000001A9 7467                            JZ      CLRET
   381 000001AB A0[0000]                        MOV     AL,[SECCLUSPOS]
   382 000001AE FEC0                            inc al
   383 000001B0 7406                    	jz @F
   384 000001B2 263A4604                        CMP     AL,[ES:BP + dpb_cluster_mask]
   385 000001B6 7657                            JBE     SAVPOS
   386                                  @@:
   387 000001B8 8B1E[0000]                      MOV     BX,[CLUSNUM]
   388 000001BC E8(0000)                        Invoke  IsEOF
   389 000001BF 7353                            JAE     NONEXT
   390                                  ;; 11/5/86 FastSeek
   391 000001C1 F606[0000]80                    TEST    byte [FastSeekflg],Fast_yes            ; fastseek installed?         ;AN000;
   392 000001C6 7430                            JZ      do_norm2                          ; no                          ;AN000;
   393 000001C8 FF36[0000]                      PUSH    word [LASTPOS]               ; save logical cluster #                ;AN000;
   394 000001CC 8F06[0000]                      POP     word [FSeek_logclus]                                                 ;AN000;
   395 000001D0 FF06[0000]                      INC     word [FSeek_logclus]         ; get next cluster                      ;AN000;
   396                                                                                                                  ;AN000;
   397 000001D4 F606[0000]01                    TEST    byte [FastSeekflg],FS_begin  ; from R/W                              ;AN000;
   398 000001D9 741D                            JZ      do_norm2                ; no                                    ;AN000;
   399                                  look2:                                                                          ;AN000;
   400 000001DB E8(0000)                        invoke  FastSeek_Lookup         ; call lookup                           ;AN000;
   401 000001DE 7325                            JNC     clusgot                 ; found one                             ;AN000;
   402                                  
   403 000001E0 83FF01                          CMP     DI,1                              ; valid drive ,e.g. C,D...    ;AN000;
   404 000001E3 7507                            JNZ     parfound2                         ; yes,                        ;AN000;
   405 000001E5 8026[0000]80                    AND     byte [FastSeekflg],Fast_yes            ; no more, fastseek           ;AN000;
   406 000001EA EB0C                            JMP     SHORT do_norm2                                                  ;AN000;
   407                                  parfound2:
   408 000001EC E80E02                          CALL    FS_TRUNC_EOF            ; check EOF                             ;AN000;
   409 000001EF 8B1E[0000]                      MOV     BX,[CLUSNUM]            ; don't need partially found cluster
   410 000001F3 800E[0000]02                    OR      byte [FastSeekflg],FS_insert ; prepared for cluster insertion        ;AN000;
   411                                                                          ; use the old bx                        ;AN000;
   412                                                                                                                  ;AN000;
   413                                  do_norm2:
   414 000001F8 E8(0000)                        invoke  UNPACK
   415 000001FB 7217                            JC      NONEXT
   416 000001FD E8(0000)                        invoke  FastSeek_Insert         ; call insert                           ;AN000;
   417 00000200 8026[0000]FD                    AND     byte [FastSeekflg],FS_no_insert  ; clear insert flag                 ;AN000;
   418                                                                                                                  ;AN000;
   419                                  clusgot:
   420                                  ;; 11/5/86 FastSeek
   421 00000205 893E[0000]                      MOV     [CLUSNUM],DI
   422 00000209 FF06[0000]                      INC     word [LASTPOS]
   423 0000020D B000                            MOV     AL,0
   424                                  SAVPOS:
   425 0000020F A2[0000]                        MOV     [SECCLUSPOS],AL
   426                                  CLRET:
   427 00000212 F8                              CLC
   428 00000213 C3                              return
   429                                  NONEXT:
   430 00000214 F9                              STC
   431 00000215 C3                              return
   432                                  EndProc NEXTSEC
   433                                  
   434                                  Break   <OPTIMIZE -- DO A USER DISK REQUEST WELL>
   435                                  
   436                                  ; Inputs:
   437                                  ;       BX = Physical cluster
   438                                  ;       CX = No. of records
   439                                  ;       DL = sector within cluster
   440                                  ;       ES:BP = Base of drives parameters
   441                                  ;       [NEXTADD] = transfer address
   442                                  ; Outputs:
   443                                  ;       AX = No. of records remaining
   444                                  ;       BX = Transfer address
   445                                  ;       CX = No. or records to be transferred
   446                                  ;       DX = Physical sector address            (LOW)
   447                                  ;       [HIGH_SECTOR] = Physical sector address (HIGH)
   448                                  ;       DI = Next cluster
   449                                  ;       [CLUSNUM] = Last cluster accessed
   450                                  ;       [NEXTADD] updated
   451                                  ;       Carry set if error (currently user FAILed to I 24)
   452                                  ; ES:BP unchanged. Note that segment of transfer not set.
   453                                  
   454                                          procedure   OPTIMIZE,NEAR
   454          ******************       warning: proc OPTIMIZE... [-w+user]
   455                                          DOSAssume   CS,<DS>,"Optimize"
   456                                          ASSUME  ES:NOTHING
   457                                  
   458                                          Assert      ISDPB,<ES,BP>,"Optimize"
   459 00000216 52                              PUSH    DX
   460 00000217 53                              PUSH    BX
   461 00000218 B400                    	mov ah, 0
   462 0000021A 268A4604                	mov al, [ES:BP + dpb_cluster_mask]
   463 0000021E 40                      	inc ax			; Number of sectors per cluster
   464 0000021F A3[0000]                	mov word ptr [Cluster_Next_EDR], ax
   465 00000222 B600                    	mov dh, 0
   466 00000224 29D0                    	sub ax, dx		; ax = Number of sectors left in first cluster
   467 00000226 89CA                            MOV     DX,CX
   468 00000228 31C9                            xor cx, cx
   469                                  ;;; 11/5/86 FastSeek
   470 0000022A FF36[0000]                      PUSH    word [LASTPOS]               ; save logical cluster #                ;AN000;
   471 0000022E 8F06[0000]                      POP     word [FSeek_logclus]                                                 ;AN000;
   472 00000232 FF06[0000]                      INC     word [FSeek_logclus]         ; get next cluster                      ;AN000;
   473                                                                                                                  ;AN000;
   474                                  OPTCLUS:
   475                                  ; lDOS obsolete:
   476                                  ; AL has number of sectors available in current cluster
   477                                  ; AH has number of sectors available in next cluster
   478                                  ; lDOS update:
   479                                  ; ax = number of sectors available in current cluster
   480                                  ; [Cluster_Next_EDR] = number of sectors available in next cluster
   481                                  
   482                                  ; BX has current physical cluster
   483                                  ; CX has number of sequential sectors found so far
   484                                  ; DX has number of sectors left to transfer
   485                                  ; ES:BP Points to DPB
   486                                  ; ES:SI has FAT pointer
   487                                  
   488 00000236 F606[0000]80                    TEST    byte [FastSeekflg],Fast_yes            ; fastseek installed?         ;AN000;
   489 0000023B 7429                            JZ      do_norm3                          ; no                          ;AN000;
   490 0000023D F606[0000]01                    TEST    byte [FastSeekflg],FS_begin            ; from R/W                    ;AN000;
   491 00000242 7422                            JZ      do_norm3                          ; no                          ;AN000;
   492 00000244 F606[0000]02                    TEST    byte [FastSeekflg],FS_insert           ; is in insert mode ?         ;AN000;
   493 00000249 751B                            JNZ     do_norm3                          ; yes                         ;AN000;
   494 0000024B E8(0000)                        invoke  FastSeek_Lookup                   ; call lookup                 ;AN000;
   495 0000024E 731B                            JNC     clusgot2                          ; found one                   ;AN000;
   496                                  
   497 00000250 83FF01                          CMP     DI,1                              ; valid drive ,e.g. C,D...    ;AN000;
   498 00000253 7507                            JNZ     par_found3                        ; yes,                        ;AN000;
   499 00000255 8026[0000]80                    AND     byte [FastSeekflg],Fast_yes            ; no more, fastseek           ;AN000;
   500 0000025A EB0A                            JMP     SHORT do_norm3                                                  ;AN000;
   501                                  par_found3:
   502 0000025C 53                              PUSH    BX
   503 0000025D E89D01                          CALL    FS_TRUNC_EOF                      ; file entry not existing     ;AN000;
   504 00000260 5B                              POP     BX                                                              ;AN000;
   505 00000261 800E[0000]02                    OR      byte [FastSeekflg],FS_insert           ; prepare for insertion       ;AN000;
   506                                                                                    ; use old bx                  ;AN000;
   507                                  do_norm3:
   508 00000266 E8(0000)                        invoke  UNPACK
   509 00000269 7241                            JC      OP_ERR
   510                                  clusgot2:
   511 0000026B E8(0000)                        invoke  FastSeek_Insert         ; call insert                           ;AN000;
   512 0000026E FF06[0000]                      INC     word [FSeek_logclus]         ; insert to next position               ;AN000;
   513                                  ;;; 11/5/86 FastSeek                                                            ;AN000;
   514 00000272 01C1                            add cx, ax
   515 00000274 39D1                            CMP     CX,DX
   516 00000276 733E                            JAE     BLKDON
   517 00000278 A1[0000]                        MOV     ax, word ptr [Cluster_Next_EDR]
   518 0000027B 43                              INC     BX
   519 0000027C 39DF                            CMP     DI,BX
   520 0000027E 74B6                            JZ      OPTCLUS
   521 00000280 4B                              DEC     BX
   522                                  FINCLUS:
   523 00000281 891E[0000]                      MOV     [CLUSNUM],BX    ; Last cluster accessed
   524 00000285 29CA                            SUB     DX,CX           ; Number of sectors still needed
   525 00000287 52                              PUSH    DX
   526 00000288 89C8                            MOV     AX,CX
   527 0000028A 26F76602                        MUL     word [ES:BP + dpb_sector_size]  ; Number of sectors times sector size
   528 0000028E 8B36[0000]                      MOV     SI,[NEXTADD]
   529 00000292 01F0                            ADD     AX,SI           ; Adjust by size of transfer
   530 00000294 A3[0000]                        MOV     [NEXTADD],AX
   531 00000297 58                              POP     AX              ; Number of sectors still needed
   532 00000298 5A                              POP     DX              ; Starting cluster
   533 00000299 29D3                            SUB     BX,DX           ; Number of new clusters accessed
   534 0000029B 011E[0000]                      ADD     [LASTPOS],BX
   535 0000029F 5B                              POP     BX              ; BL = sector postion within cluster
   536 000002A0 E82200                          invoke  FIGREC
   537 000002A3 89F3                            MOV     BX,SI
   538 000002A5 8026[0000]FD                    AND     byte [FastSeekflg],FS_no_insert  ; clear insert flag
   539 000002AA F8                              CLC
   540 000002AB C3                              return
   541                                  
   542                                  OP_ERR:
   543 000002AC 83C404                          ADD     SP,4
   544 000002AF 8026[0000]FD                    AND     byte [FastSeekflg],FS_no_insert  ; clear insert flag
   545 000002B4 F9                              STC
   546 000002B5 C3                              return
   547                                  
   548                                  BLKDON:
   549 000002B6 29D1                            SUB     CX,DX           ; Number of sectors in cluster we don't want
   550 000002B8 A1[0000]                	mov ax, word ptr [Cluster_Next_EDR]
   551 000002BB 29C8                            sub ax, cx		; Number of sectors in cluster we accepted
   552 000002BD 48                              dec ax			; Adjust to mean position within cluster
   553 000002BE A2[0000]                        MOV     [SECCLUSPOS], al
   554 000002C1 89D1                            MOV     CX,DX           ; Anyway, make the total equal to the request
   555 000002C3 EBBC                            JMP     SHORT FINCLUS
   556                                  EndProc OPTIMIZE
   557                                  
   558                                  Break   <FIGREC -- Figure sector in allocation unit>
   559                                  
   560                                  ; Inputs:
   561                                  ;       DX = Physical cluster number
   562                                  ;       BL = Sector postion within cluster
   563                                  ;       ES:BP = Base of drive parameters
   564                                  ; Outputs:
   565                                  ;       DX = physical sector number           (LOW)
   566                                  ;       [HIGH_SECTOR] Physical sector address (HIGH)
   567                                  ; No other registers affected.
   568                                  
   569                                          procedure   FIGREC,NEAR
   569          ******************       warning: proc FIGREC... [-w+user]
   570                                  ASSUME  DS:NOTHING,ES:NOTHING
   571                                  
   572                                          Assert      ISDPB,<ES,BP>,"FigRec"
   573 000002C5 51                              PUSH    CX
   574 000002C6 31C9                    	xor cx, cx
   575 000002C8 268A4E05                        MOV     CL,[ES:BP + dpb_cluster_shift]
   576 000002CC 4A                              DEC     DX
   577 000002CD 4A                              DEC     DX
   578 000002CE 36C706[0000]0000                MOV     word [ss:HIGH_SECTOR],0              ;F.C. >32mb
   579 000002D5 E309                            jcxz    noshift                      ;F.C. >32mb
   580                                  rotleft:                                     ;F.C. >32mb
   581 000002D7 D1E2                            shl     DX,1                         ;F.C. >32mb
   582 000002D9 36D116[0000]                    RCL     word [ss:HIGH_SECTOR],1              ;F.C. >32mb
   583 000002DE E2F7                            LOOP    rotleft                      ;F.C. >32mb
   584                                  noshift:
   585                                  
   586                                  ;       SHL     DX,CL
   587 000002E0 08DA                            OR      DL,BL
   588 000002E2 2603560B                        ADD     DX,[ES:BP + dpb_first_sector]
   589 000002E6 368316[0000]00                  ADC     word [ss:HIGH_SECTOR],0              ;F.C. >32mb
   590 000002EC 59                              POP     CX
   591 000002ED C3                              return
   592                                  EndProc FIGREC
   593                                  
   594                                  Break   <ALLOCATE -- Assign disk space>
   595                                  
   596                                  ;***    ALLOCATE - Allocate Disk Space
   597                                  ;
   598                                  ;   ALLOCATE is called to allocate disk clusters.  The new clusters are
   599                                  ;   FAT-chained onto the end of the existing file.
   600                                  ;
   601                                  ;   The DPB contains the cluster # of the last free cluster allocated
   602                                  ;   (dpb_next_free).  We start at this cluster and scan towards higher
   603                                  ;   numbered clusters, looking for the necessary free blocks.
   604                                  ;
   605                                  ;   Once again, fancy terminology gets in the way of corrct coding.  When
   606                                  ;   using next_free, start scanning AT THAT POINT and not the one following it.
   607                                  ;   This fixes the boundary condition bug when only free = next_free = 2.
   608                                  ;
   609                                  ;       If we get to the end of the disk without satisfaction:
   610                                  ;
   611                                  ;           if (dpb_next_free == 2) then we've scanned the whole disk.
   612                                  ;               return (insufficient_disk_space)
   613                                  ;           ELSE
   614                                  ;               dpb_next_free = 2; start scan over from the beginning.
   615                                  ;
   616                                  ;   Note that there is no multitasking interlock.  There is no race when
   617                                  ;   examining the entrys in an in-core FAT block since there will be no
   618                                  ;   context switch.  When UNPACK context switches while waiting for a FAT read
   619                                  ;   we are done with any in-core FAT blocks, so again there is no race.  The
   620                                  ;   only special concern is that V2 and V3 MSDOS left the last allocated
   621                                  ;   cluster as "00"; marking it EOF only when the entire alloc request was
   622                                  ;   satisfied.  We can't allow another activation to think this cluster is
   623                                  ;   free, so we give it a special temporary mark to show that it is, indeed,
   624                                  ;   allocated.
   625                                  ;
   626                                  ;   Note that when we run out of space this algorithem will scan from
   627                                  ;   dpb_next_free to the end, then scan from cluster 2 through the end,
   628                                  ;   redundantly scanning the later part of the disk.  This only happens when
   629                                  ;   we run out of space, so sue me.
   630                                  ;
   631                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   632                                  ;            C  A  V  E  A  T     P  A  T  T  E  R  S  O  N                ;
   633                                  ;                                                                          ;
   634                                  ;   The use of FATBYT and RESTFATBYT is somewhat mysterious.  Here is the
   635                                  ;   explanation:
   636                                  ;
   637                                  ;   In the NUL file case (sf_firclus currently 0) ALLOCATE is called with
   638                                  ;   entry BX = 0.  What needs to be done in this case is to stuff the cluster
   639                                  ;   number of the first cluster allocated in sf_firclus when the ALLOCATE is
   640                                  ;   complete.  THIS VALUE IS SAVED TEMPORARILY IN CLUSTER 0, HENCE THE CURRENT
   641                                  ;   VALUE IN CLUSTER 0 MUST BE SAVED AND RESTORED.  This is a side effect of
   642                                  ;   the fact that PACK and UNPACK don't treat requests for clusters 0 and 1 as
   643                                  ;   errors.  This "stuff" is done by the call to PACK which is right before
   644                                  ;   the
   645                                  ;           LOOP    findfre         ; alloc more if needed
   646                                  ;   instruction when the first cluster is allocated to the nul file.  The
   647                                  ;   value is recalled from cluster 0 and stored at sf_firclus at ads4:
   648                                  ;
   649                                  ;   This method is obviously useless (because it is non-reentrant) for
   650                                  ;   multitasking, and will have to be changed.  Storing the required value on
   651                                  ;   the stack is recommended.  Setting sf_firclus at the PACK of cluster 0
   652                                  ;   (instead of actually doing the PACK) is BAD because it doesn't handle
   653                                  ;   problems with INT 24 well.
   654                                  ;
   655                                  ;            C  A  V  E  A  T     P  A  T  T  E  R  S  O  N                ;
   656                                  ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
   657                                  ;                                                                          ;
   658                                  ;       ENTRY   BX = Last cluster of file (0 if null file)
   659                                  ;               CX = No. of clusters to allocate
   660                                  ;               ES:BP = Base of drive parameters
   661                                  ;               [THISSFT] = Points to SFT
   662                                  ;
   663                                  ;       EXIT    'C' set if insufficient space
   664                                  ;                 [FAILERR] can be tested to see the reason for failure
   665                                  ;                 CX = max. no. of clusters that could be added to file
   666                                  ;               'C' clear if space allocated
   667                                  ;                 BX = First cluster allocated
   668                                  ;                 FAT is fully updated
   669                                  ;                 sf_FIRCLUS field of SFT set if file was null
   670                                  ;
   671                                  ;       USES    ALL but SI, BP
   672                                  
   673                                          PROCEDURE   ALLOCATE,NEAR
   673          ******************       warning: proc ALLOCATE... [-w+user]
   674                                  
   675                                          DOSAssume   CS,<DS>,"Allocate"
   676                                          ASSUME  ES:NOTHING
   677                                  
   678                                          Assert      ISDPB,<ES,BP>,"Allocate"
   679 000002EE 53                              PUSH    BX                      ; save (bx)
   680 000002EF 31DB                            XOR     BX,BX
   681 000002F1 E8(0000)                        invoke  UNPACK
   682 000002F4 893E[0000]                      MOV     [FATBYT],DI             ; save correct cluster 0 value
   683 000002F8 5B                              POP     BX
   684 000002F9 72F2                            retc                            ; abort if error   [INTERR?]
   685                                  
   686 000002FB 51                              PUSH    CX
   687 000002FC 53                              PUSH    BX
   688                                  
   689 000002FD 89DA                            MOV     DX,BX
   690                                          Assert      ISDPB,<ES,BP>,"Allocate/Unpack"
   691 000002FF 268B5E1D                        mov     bx,[es:bp + dpb_next_free]
   692 00000303 83FB02                          cmp     bx,2
   693                                  findfre equ FINDFRE	; NASM port label
   694 00000306 7709                            ja      findfre
   695                                  
   696                                  ;   couldn't find enough free space beyond dpb_next_free, or dpb_next_free is
   697                                  ;   <2 or >dpb_max_clus.  Reset it and restart the scan
   698                                  
   699                                  ads1:
   700                                          Assert      ISDPB,<ES,BP>,"Alloc/ads1"
   701 00000308 26C7461D0200                    mov     word [es:bp + dpb_next_free],2
   702 0000030E BB0100                          mov     bx,1                    ; Counter next instruction so first
   703                                                                          ;       cluster examined is 2
   704                                  
   705                                  ;   Scanning both forwards and backwards for a free cluster
   706                                  ;
   707                                  ;       (BX) = forwards scan pointer
   708                                  ;       (CX) = clusters remaining to be allocated
   709                                  ;       (DX) = current last cluster in file
   710                                  ;       (TOS) = last cluster of file
   711                                  
   712                                  FINDFRE:
   713 00000311 43                              INC     BX
   714                                          Assert      ISDPB,<ES,BP>,"Alloc/findfre"
   715 00000312 263B5E0D                        CMP     BX,[ES:BP + dpb_max_cluster]
   716 00000316 7603                            JBE     aupk
   717 00000318 EB77                            jmp     ads7            ; at end of disk
   718 0000031A 90                      	nop	; identicalise
   719                                  aupk:
   720 0000031B E8(0000)                        invoke  UNPACK          ; check out this cluster
   721 0000031E 722F                            jc      ads4            ; FAT error             [INTERR?]
   722 00000320 75EF                            jnz     findfre         ; not free, keep on truckin
   723                                  
   724                                  ;   Have found a free cluster.  Chain it to the file
   725                                  ;
   726                                  ;       (BX) = found free cluster #
   727                                  ;       (DX) = current last cluster in file
   728                                  
   729 00000322 26895E1D                        mov     [es:bp + dpb_next_free],bx        ; next time start search here
   730 00000326 92                              xchg    ax,dx           ; save (dx) in ax
   731 00000327 BA0100                          mov     dx,1            ; mark this free guy as "1"
   732 0000032A E8(0000)                        invoke  PACK            ; set special "temporary" mark
   733 0000032D 7220                            jc      ads4            ; FAT error             [INTERR?]
   734 0000032F 26837E1FFF                      CMP     word [ES:BP + dpb_free_cnt],-1 ; Free count valid?
   735 00000334 7404                            JZ      NO_ALLOC                ; No
   736 00000336 26FF4E1F                        DEC     word [ES:BP + dpb_free_cnt]    ; Reduce free count by 1
   737                                  NO_ALLOC:
   738 0000033A 92                              xchg    ax,dx           ; (dx) = current last cluster in file
   739 0000033B 87DA                            XCHG    BX,DX
   740 0000033D 89D0                            MOV     AX,DX
   741 0000033F E8(0000)                        invoke  PACK            ; link free cluster onto file
   742                                                                  ;  CAVEAT.. On Nul file, first pass stuffs
   743                                                                  ;    cluster 0 with FIRCLUS value.
   744 00000342 720B                            jc      ads4            ; FAT error             [INTERR?]
   745 00000344 93                              xchg    BX,AX           ; (BX) = last one we looked at
   746 00000345 89DA                            mov     dx,bx           ; (dx) = current end of file
   747 00000347 E2C8                            LOOP    findfre         ; alloc more if needed
   748                                  
   749                                  ;   We've successfully extended the file.  Clean up and exit
   750                                  ;
   751                                  ;       (BX) = last cluster in file
   752                                  
   753 00000349 BAFFFF                          MOV     DX,0FFFFH
   754 0000034C E8(0000)                        invoke  PACK            ; mark last cluster EOF
   755                                  
   756                                  ;   Note that FAT errors jump here to clean the stack and exit.  this saves us
   757                                  ;   2 whole bytes.  Hope its worth it...
   758                                  ;
   759                                  ;       'C' set iff error
   760                                  ;       calling (BX) and (CX) pushed on stack
   761                                  
   762 0000034F 5B                      ads4:   POP     BX
   763 00000350 59                              POP     CX              ; Don't need this stuff since we're successful
   764 00000351 729A                            retc
   765 00000353 E8(0000)                        invoke  UNPACK          ; Get first cluster allocated for return
   766                                                                  ; CAVEAT... In nul file case, UNPACKs cluster 0.
   767 00000356 7295                            retc
   768 00000358 E85400                          invoke  RESTFATBYT      ; Restore correct cluster 0 value
   769 0000035B 7290                            retc
   770 0000035D 87DF                            XCHG    BX,DI           ; (DI) = last cluster in file upon our entry
   771 0000035F 09FF                            OR      DI,DI           ; clear 'C'
   772 00000361 758A                            retnz                   ; we were extending an existing file
   773                                  
   774                                  ;   We were doing the first allocation for a new file.  Update the SFT cluster
   775                                  ;   info
   776                                  ;; Extended Attributes
   777                                  ;       TEST    [XA_condition],XA_No_SFT      ;FT. don't update SFT when from   ;AN000;
   778                                  ;       JZ      dofastk                       ;FT. GetSet_XA                    ;AN000;
   779                                  ;       AND     [XA_condition],not XA_No_SFT  ;FT. clear the bit                ;AN000;
   780                                  ;       CLC                                   ;FT.                              ;AN000;
   781                                  ;       ret                                   ;FT.                              ;AN000;
   782                                  ;; 11/6/86 FastSeek
   783                                  dofastk:
   784 00000363 52                              PUSH    DX
   785 00000364 268A5600                        MOV     DL,[ES:BP + dpb_drive]              ; get drive #
   786                                  
   787 00000368 06                              PUSH    ES
   788 00000369 C43E[0000]                      LES     DI,[THISSFT]
   789                                          Assert  ISSFT,<ES,DI>,"Allocate/ads4"
   790 0000036D 26895D0B                        MOV     [ES:DI + sf_firclus],BX
   791 00000371 26895D35                        MOV     [ES:DI + sf_lstclus],BX
   792                                  
   793 00000375 F606[0000]80                    TEST    byte [FastSeekflg],Fast_yes           ; fastseek installed
   794 0000037A 7412                            JZ      do_norm5                         ; no
   795 0000037C F606[0000]01                    TEST    byte [FastSeekflg],FS_begin           ; do fastseek
   796 00000381 740B                            JZ      do_norm5                          ; no
   797 00000383 51                              PUSH    CX
   798 00000384 89D9                            MOV     CX,BX                             ; set up firclus #
   799 00000386 891E[0000]                      MOV     [FSeek_firclus],BX                ; update firclus varible
   800 0000038A E8(0000)                        invoke  FastSeek_Open                     ; create this file entry
   801 0000038D 59                              POP     CX
   802                                  do_norm5:
   803 0000038E 07                              POP     ES
   804                                   assume es:nothing
   805                                  ;; 11/6/86 FastSeek
   806 0000038F 5A                              POP     DX
   807 00000390 C3                              return
   808                                  
   809                                  
   810                                  ;** we're at the end of the disk, and not satisfied.  See if we've scanned ALL
   811                                  ;   of the disk...
   812                                  
   813 00000391 26837E1D02              ads7:   cmp     word [es:bp + dpb_next_free],2
   814                                  %ifn debug
   815 00000396 7403                            jz      tmplab2         ;
   816 00000398 E96DFF                          jmp     ads1            ; start scan from front of disk
   817                                  tmplab2:
   818                                  %else
   819                                          jz      tmplab
   820                                          jmp     ads1
   821                                  tmplab:
   822                                  %endif
   823                                  
   824                                  ;   Sorry, we've gone over the whole disk, with insufficient luck.  Lets give
   825                                  ;   the space back to the free list and tell the caller how much he could have
   826                                  ;   had.  We have to make sure we remove the "special mark" we put on the last
   827                                  ;   cluster we were able to allocate, so it doesn't become orphaned.
   828                                  ;
   829                                  ;       (CX) = clusters remaining to be allocated
   830                                  ;       (TOS) = last cluster of file (before call to ALLOCATE)
   831                                  ;       (TOS+1) = # of clusters wanted to allocate
   832                                  
   833                                  
   834 0000039B 5B                              POP     BX              ; (BX) = last cluster of file
   835 0000039C BAFFFF                          MOV     DX,0FFFFH
   836 0000039F E81F00                          invoke  RELBLKS         ; give back any clusters just alloced
   837 000003A2 58                              POP     AX              ; No. of clusters requested
   838                                                                  ; Don't "retc". We are setting Carry anyway,
   839                                                                  ;   Alloc failed, so proceed with return CX
   840                                                                  ;   setup.
   841 000003A3 29C8                            SUB     AX,CX           ; AX=No. of clusters allocated
   842 000003A5 E80700                          invoke  RESTFATBYT      ; Don't "retc". We are setting Carry anyway,
   843                                                                  ;   Alloc failed.
   844                                  ;       fmt     <>,<>,<"$p: disk full in allocate\n">
   845 000003A8 C606[0000]01                    MOV     byte [DISK_FULL],1   ;MS. indicating disk full
   846 000003AD F9                              STC
   847 000003AE C3                              return
   848                                  
   849                                  EndProc ALLOCATE
   850                                  
   851                                  ; SEE ALLOCATE CAVEAT
   852                                  ;       Carry set if error (currently user FAILed to I 24)
   853                                  
   854                                          procedure   RESTFATBYT,NEAR
   854          ******************       warning: proc RESTFATBYT... [-w+user]
   855                                          DOSAssume   CS,<DS>,"RestFATByt"
   856                                          ASSUME  ES:NOTHING
   857                                  
   858 000003AF 53                              PUSH    BX
   859 000003B0 52                              PUSH    DX
   860 000003B1 57                              PUSH    DI
   861 000003B2 31DB                            XOR     BX,BX
   862 000003B4 8B16[0000]                      MOV     DX,[FATBYT]
   863 000003B8 E8(0000)                        invoke  PACK
   864 000003BB 5F                              POP     DI
   865 000003BC 5A                              POP     DX
   866 000003BD 5B                              POP     BX
   867 000003BE C3                              return
   868                                  EndProc RESTFATBYT
   869                                  
   870                                  Break   <RELEASE -- DEASSIGN DISK SPACE>
   871                                  
   872                                  ; Inputs:
   873                                  ;       BX = Cluster in file
   874                                  ;       ES:BP = Base of drive parameters
   875                                  ; Function:
   876                                  ;       Frees cluster chain starting with [BX]
   877                                  ;       Carry set if error (currently user FAILed to I 24)
   878                                  ; AX,BX,DX,DI all destroyed. Other registers unchanged.
   879                                  
   880                                          procedure   RELEASE,NEAR
   880          ******************       warning: proc RELEASE... [-w+user]
   881                                          DOSAssume   CS,<DS>,"Release"
   882                                          ASSUME  ES:NOTHING
   883                                  
   884 000003BF 31D2                            XOR     DX,DX
   885                                  entry   RELBLKS
   886                                          DOSAssume   CS,<DS>,"RelBlks"
   887                                          Assert      ISDPB,<ES,BP>,"RelBlks"
   888                                  
   889                                  ;   Enter here with DX=0FFFFH to put an end-of-file mark in the first cluster
   890                                  ;   and free the rest in the chain.
   891                                  
   892 000003C1 E8(0000)                        invoke  UNPACK
   893 000003C4 72F8                            retc
   894 000003C6 74F6                            retz
   895 000003C8 89F8                            MOV     AX,DI
   896 000003CA 52                              PUSH    DX
   897 000003CB E8(0000)                        invoke  PACK
   898 000003CE 5A                              POP     DX
   899 000003CF 72ED                            retc
   900 000003D1 09D2                            OR      DX,DX
   901 000003D3 750B                            JNZ     NO_DEALLOC              ; Was putting EOF mark
   902 000003D5 26837E1FFF                      CMP     word [ES:BP + dpb_free_cnt],-1 ; Free count valid?
   903 000003DA 7404                            JZ      NO_DEALLOC              ; No
   904 000003DC 26FF461F                        INC     word [ES:BP + dpb_free_cnt]    ; Increase free count by 1
   905                                  NO_DEALLOC:
   906 000003E0 89C3                            MOV     BX,AX
   907 000003E2 48                              dec     ax              ; check for "1"
   908 000003E3 74D9                            retz                    ; is last cluster of incomplete chain
   909 000003E5 E8(0000)                        Invoke  IsEOF
   910 000003E8 72D5                            JB      RELEASE         ; Carry clear if JMP not taken
   911 000003EA C3                      ret12:  return
   912                                  EndProc RELEASE
   913                                  
   914                                  Break   <GETEOF -- Find the end of a file>
   915                                  
   916                                  ; Inputs:
   917                                  ;       ES:BP Points to DPB
   918                                  ;       BX = Cluster in a file
   919                                  ;       DS = CS
   920                                  ; Outputs:
   921                                  ;       BX = Last cluster in the file
   922                                  ;       Carry set if error (currently user FAILed to I 24)
   923                                  ; DI destroyed. No other registers affected.
   924                                  
   925                                          procedure   GETEOF,NEAR
   925          ******************       warning: proc GETEOF... [-w+user]
   926                                          DOSAssume   CS,<DS>,"GetEOF"
   927                                          ASSUME  ES:NOTHING
   928                                  
   929                                          Assert      ISDPB,<ES,BP>,"GetEof"
   930 000003EB E8(0000)                        invoke  UNPACK
   931 000003EE 72FA                            retc
   932 000003F0 53                              PUSH    BX
   933 000003F1 89FB                            MOV     BX,DI
   934 000003F3 E8(0000)                        Invoke  IsEOF
   935 000003F6 5B                              POP     BX
   936                                  RET12 equ ret12	; NASM port label
   937 000003F7 73F1                            JAE     RET12           ; Carry clear if jmp
   938 000003F9 89FB                            MOV     BX,DI
   939 000003FB EBEE                            JMP     GETEOF
   940                                  EndProc GETEOF
   941                                  
   942                                  Break   <FS_TRUNC_EOF - truncate EOF for Fastseek>
   943                                  
   944                                  ; Inputs:
   945                                  ;       ES:BP Points to DPB
   946                                  ;       BX = Cluster in a file
   947                                  ; Functions: if BX=EOF then truncate it from Fastseek Cache
   948                                  ; Outputs:
   949                                  ;       carry set: not EOF
   950                                  ;       carry clear: EOF and do truncate
   951                                  
   952                                          procedure   FS_TRUNC_EOF,NEAR
   952          ******************       warning: proc FS_TRUNC_EOF... [-w+user]
   953                                          ASSUME  ES:NOTHING,DS:NOTHING
   954                                  
   955 000003FD 89FB                            MOV     BX,DI                             ; get beginning physical#     ;AN000;
   956 000003FF E8(0000)                        invoke  IsEOF                             ; is EOF                      ;AN000;
   957 00000402 7218                            JB      noteof2                           ; no                          ;AN000;
   958 00000404 36FF36[0000]                    PUSH    word [ss:FSeek_logclus]                   ;                             ;AN000;
   959 00000409 36FF36[0000]                    PUSH    word [ss:FSeek_logsave]                   ; logclus=logsave             ;AN000;
   960 0000040E 368F06[0000]                    POP     word [ss:FSeek_logclus]                   ; delete EOF                  ;AN000;
   961 00000413 E8(0000)                        invoke  FastSeek_Truncate                 ;                             ;AN000;
   962 00000416 368F06[0000]                    POP     word [ss:FSeek_logclus]                   ; redo the look up            ;AN000;
   963 0000041B F8                              CLC                                                                     ;AN000;
   964                                  noteof2:                                                                        ;AN000;
   965 0000041C C3                              return                                                                  ;AN000;
   966                                  EndProc FS_TRUNC_EOF                                                            ;AN000;
   967                                  
   968                                      END
   969                                  
   970                                  
