

FAT12_next_cluster proc far
; AX    = actual
; ES:SI = fat table

        ; (cluster * 3) / 2

        mov  bx, 3
        xor  dx, dx
        mul  bx
        shr  ax, 1

        mov  bp, ax
        mov  ax, word ptr es:[si+bp]

        ; If the cluster number was even, the cluster value is now in
        ; bits 0-11 of AX. If the cluster number was odd, the cluster
        ; value is in bits 4-15, and must be shifted right 4 bits. If
        ; the number was odd, CF was set in the last shift instruction.
        mov  dx, ax
        test dx, 1
        jnc  fateven
        mov  cl, 4      
        shr  ax, cl          ; shift the cluster number 
fateven:
        and  ah, 0fh         ; mask off the highest 4 bits
        cmp  ax, 0fffh       ; check for EOF
        jmp  nexttest
nexttest:
        jae  fat_EOF          ; continue if not EOF
_finished:
        clc
        jmp  ncx
fat_EOF:
        ; CF=1 ax=NZ = EOF
        stc
        jmp  ncx
FAT_Error:
        ; CF=1 ax=0 = error
        xor  ax, ax
        stc
ncx:    ret
FAT12_next_cluster endp

; copy between drives :
;
; loadimage from disk 1
; unmount first floppy
; mount 2nd floppy
; saveimage to disk 2
; unmount 2nd floppy
; mount 1st floppy


FAT12_loadimage2 proc far
;       loadFile: Loads the file into memory, one cluster at a time.
; si = FATCHAIN entry (cluster)
; ES:BX = load address
cluster_next:
          push ax  ; cluster
          push bx  ; offset
          lea  si, FAT12_FAT
fat_12:   ; First cluster is cluster 2
          dec  ax
          dec  ax
          xor  dx, dx
          xor  cx, cx
          mov  cl, bSectsperclust
          mul  cx          ; (((cluster - 2)*CPS)+FAT12_data_start) = logical sector
          add  ax, FAT12_data_start
          mov  di, 1                   ; Sector count
          call readdisk
          jc   loadfile_error
          ; If the cluster number was even, the cluster value is now in
          ; bits 0-11 of AX. If the cluster number was odd, the cluster
          ; value is in bits 4-15, and must be shifted right 4 bits. If
          ; the number was odd, CF was set in the last shift instruction.
          pop  bx
          pop  ax
          add  bx, wSectsize

          mov  bx, 3
          xor  dx, dx
          mul  bx
          shr  ax, 1
          ; (N*3)/2 = sector

          mov  bp, ax
          mov  ax, word ptr [si][bp]
          jnc     fat_even
          mov     cl, 4
          shr     ax, cl
fat_even: and     ah, 0fh       ; mask off the highest 4 bits
          cmp     ax, 0ff8h     ; check for EOF
          jb      cluster_next      ; continue if not EOF
loadfile_error:
          ret
FAT12_loadimage2 endp
; --- code and notes follows ------------------------------------------------

;FAT12_Tempbuf db 512 dup(0)

;FAT12_GETFATCHAIN  proc far
;       GETFATCHAIN:    
;
;       Reads the FAT chain and stores it in a temporary buffer in the first
;       64 kb.  The FAT chain is stored an array of 16-bit cluster numbers,
;       ending with 0.
;       
;       The file must fit in conventional memory, so it can't be larger than
;       640 kb. The sector size must be at least 512 bytes, so the FAT chain
;       can't be larger than around 3 kb.
;
;       Call with:      AX = first cluster in chain
;
;       Returns:        CF clear on success, set on error


;                push cs
;                pop  es
;                mov  bx, offset FAT12_FAT

		; Set ES:DI to the temporary storage for the FAT chain.
;                mov  di, offset FAT12_tempbuf


;next_clust:     stosw                           ; store cluster number
;                mov     si, ax                  ; SI = cluster number
;                cmp     byte ptr bSig, 29h
;                jne     fat_12
;                cmp     byte ptr SystemID[4], '6'  ; check for FAT-16 system
;                je      fat_16

                ; This is a FAT-12 disk.

;fat_12:         add     si, si          ; multiply cluster number by 3...
;                add     si, ax
;                shr     si, 1           ; ...and divide by 2
;                lodsw

		; If the cluster number was even, the cluster value is now in
		; bits 0-11 of AX. If the cluster number was odd, the cluster
		; value is in bits 4-15, and must be shifted right 4 bits. If
		; the number was odd, CF was set in the last shift instruction.

;                jnc     fat_even
 ;               mov     cl, 4      
 ;               shr     ax, cl          ; shift the cluster number 
		
;fat_even:       and     ah, 0fh         ; mask off the highest 4 bits
;                cmp     ax, 0fffh       ; check for EOF
;                jmp     short next_test

		; This is a FAT-16 disk. The maximal size of a 16-bit FAT
		; is 128 kb, so it may not fit within a single 64 kb segment.
 
;fat_16:         mov     dx, offset FAT12_FAT
;                add     si, si          ; multiply cluster number by two
;                jnc     first_half      ; if overflow...
;                add     dh, 10h         ; ...add 64 kb to segment value

;first_half:     mov     ds, dx          ; DS:SI = pointer to next cluster
;                lodsw                   ; AX = next cluster

;                cmp     ax, 0fff8h      ; >= FFF8 = 16-bit EOF
;next_test:      jb      next_clust      ; continue if not EOF

;finished:       ; Mark end of FAT chain with 0, so we have a single
		; EOF marker for both FAT-12 and FAT-16 systems.

;                xor     ax, ax
;                stosw
;fatError:
;                ret
;FAT12_GETFATCHAIN endp


loadFile proc far
; loadFile: Loads the file into memory, one cluster at a time.
; set ES:BX to load address

;                mov     si, offset FAT12_Tempbuf ; set DS:SI to the FAT chain
;                push    cs      
;                pop     ds              

;next_cluster:   lodsw                           ; AX = next cluster to read
;                or      ax, ax                  ; if EOF...
;                je      loadsuccess             ; ...boot was successful
;
;                dec     ax                      ; cluster numbers start with 2
;                dec     ax
;
;                mov     di, word ptr bSectsperclust
;                and     di, 0ffh                ; DI = sectors per cluster
;                mul     di                       
;                add     ax, fat12_data_start
;           ;     adc     dx, data_start+2        ; DX:AX = first sector to read
;                xor  dx, dx
;                call    readDisk
;                jnc     next_cluster            
;loadsuccess:
         ret
loadFile endp



FAT12_ReadCluster proc far
            PUSH    CX
            PUSH    DX
            PUSH    DI

            MOV     DI,AX           ; save cluster number in DI

            DEC     AX              ; make it null-based
            DEC     AX

            XOR     CX,CX           ; clear CX
            MOV     CL,bSectsperclust          ; CX=Sectors per Cluster

            CMP     CL,1            ; 1 sector per cluster??
            JE      RCSkip          ; if so, do nothing
            MUL     CX              ; else, multply by cluster size
RCSkip:
            ADD     AX,fat12_data_start   ; add start of DataArea to AX
            mov     dl, FAT12_drive
            mov     FL_drive, dl
            xor     dx, dx
            push    di
            mov     di, 1
            call    readdisk     ; read one cluster
            pop     di
            

        ; decide if we're keeping the upper or lower 12 bits
        ; of the 16-bit value we fetch from the FAT...

        ; we divide the cluster number by 1.5

                MOV     AX,3            ; cluster * 3
                MUL     DI
                MOV     DI,2            ; / 2
                DIV     DI

                MOV     DI,AX
                MOV     AX, word ptr DS:[FAT12_FAT+DI]        ; get FAT value in AX

        ; is index evenly aligned?

                OR      DX,DX           ; reminder?
                JZ      RCEven

        ; nope, keep upper bits...

                MOV     CL,4            ; yes, keep upper 12 bits
                SHR     AX,CL
RCEven:

        ; fall through and mask of bits in case...

                AND     AH,0FH          ; keep, lower 12 bits...

                POP     DI
                POP     DX
                POP     CX

                RET

FAT12_ReadCluster     ENDP 

FAT12_LoadFile Proc far
; ax = first cluster
; Load entire file into Buffer (limited to 64K)  ES:BX
         push bx
         push si
         push ds
         xor  si, si
         mov  ds, si
LFmore:
         Call FAT12_ReadCluster
         cmp  ax, 0ff7h
         je   LFdone
         cmp  ax, 0ff8h
         jae  LFdone
         push ax
         mov  ax, bx
         mov  bx, wsectsize
         add  bx, ax
         pop  ax
         jmp  LFmore
LFdone:  pop  ds
         pop  si
         pop  bx
         ret
FAT12_LoadFile endp


;    Find next cluster in the FAT, return number in AX
next_FAT_entry proc far
; AX    = cluster number 
; ES:BX = Fattable
     ; Get entry from FAT12 table
     push   bx               ; save regs
     push   cx
     mov  bx, ax
     mov  dx, 3
     mul  dx
     shr  ax, 1  ; divide by 2
     xchg bx, ax
     ; BX = Buffer
     ; AX = Current cluster
     mov  ax, word ptr es:[si][BX]
;    jnc  nc_even
;    mov    bx,ax            ; copy the number
;    shr    bx,1             ; divide by 2
;    add    bx,ax            ; new cluster offset
;    mov    dx, es:[bx]      ; DX = new cluster value
     shr    ax,1             ; old cluster even?
     jc     E1               ; no: keep high 12 bits
     and    dx,0FFFh         ; yes: keep low 12 bits
     jmp    E2
E1:  mov    cl,4             ; shift 4 bits to the right
     shr    dx,cl
E2:  mov    ax,dx            ; return new cluster number
     pop    cx               ; restore regs
     pop    bx
     ret
next_FAT_entry endp


; --------------------
; AX = CLuster no.
; SI = FAT buffer
; clc  no error AX = cluster
; stc and ax=0 end of chain
; stc and ax=1 error
         lea  si, FAT12_FAT
nextcluster:
         mov  bx, ax
         mov  dx, 3
         mul  dx
         shr  ax, 1  ; divide by 2
         xchg bx, ax
         ; BX = Buffer
         ; AX = Current cluster
         mov  ax, word ptr [si][BX]
         jnc  nc_even
nc_odd:
         shr ax, 1
         shr ax, 1
         shr ax, 1
         shr ax, 1
         jmp eoc_check
nc_even:
         and  ah, 0fh
eoc_check:
         cmp  ax, 0ff8h   ; ff7
         jc   eoc_true
         xor  ax, ax
eoc_true:
         cmc
         jmp  FAT12_LI_GCE
FAT12_LI_GCE:
; --------------------



; --------------------------------
         lea  dx, commandline
         inc  dx
         lea  bx, wEnvSeg
         call run
         call put_hex
         _newline
         ;
         _fileexist commandline
         jc   _tryalternate
         ; attempt to run \command.com
         lea  dx, commandline
         lea  bx, wEnvSeg
         call run
         jnc  _noerr2
         call put_hex
         _newline
_tryalternate:
         _fileexist altcommand
         jc   _prompt
         ; if that fails run \dos\command.com
         lea  dx, altcommand
         lea  bx, wEnvSeg
         call run
         jc   _runerror
_noerr2: jmp  _noerr1
_noerr1:  
         xor  ax, ax
_prompt:
         call bootprompt
_runerror:
         cmp  ax, 0
         je   _nomsg
         call put_hex
         _newline
         _print badormissingci, 1
_nomsg:
