; ****************************************************************************
; DIRLIST.ASM (by Erdogan Tan)
;
; 05/02/2011
;
; ****************************************************************************

; DTA (PSP+80h= Offset 128)
DTA_Attribute equ 149 ; DTA+21
DTA_Time equ 150 ; DTA+22
DTA_Date equ 152 ; DTA+24
DTA_FileSize equ 154 ; DTA + 26
DTA_FileName equ 158 ; DTA + 30

PSP_CommandTail equ 80h

.8086

SINGLIXBOOT     SEGMENT PUBLIC 'CODE'
                assume cs:SINGLIXBOOT,ds:SINGLIXBOOT,es:SINGLIXBOOT,ss:SINGLIXBOOT

                org 100h
START_CODE:

proc_start      proc near
                xor bh, bh
               
                mov si, PSP_CommandTail
                mov bl, byte ptr [SI]
                or bl, bl                               
                jnz short loc_find_file       ; jump if not zero

                int 20h

loc_find_file:
                inc si
                mov byte ptr [SI][BX], bh     ; 0 
loc_find_file_next:
                inc si
                mov al, byte ptr [SI]
                cmp al, 20h                   ; is it SPACE ?
                ja short loc_find_first_file_int21h

                dec bl                                  
                jnz short loc_find_file_next              
                
                int 20h

loc_find_first_file_int21h:
                call proc_print_directory

                int 20h

proc_start      endp


SINGLIX_PRINTMSG     proc near
 
SINGLIX_PRINTMSG_LOOP:
                lodsb                           ; Load byte at DS:SI to AL
                and     AL,AL            
                jz      short SINGLIX_PRINTMSG_OK       
                mov     AH,0Eh                  
                mov     BX,07h             
                int     10h                     ; BIOS Service func ( ah ) = 0Eh
                                                ; Write char as TTY
                                                ;AL-char BH-page BL-color
                jmp     short SINGLIX_PRINTMSG_LOOP           

SINGLIX_PRINTMSG_OK:
                retn

SINGLIX_PRINTMSG     endp

proc_print_directory proc near
                ; 05/02/2011
                ; simple derivation from trdos kernel print directory procedure
                ; in DIR.ASM (30/10/2010)
                ; INPUT -> DS:SI = Asciiz file or dir name 
                
                mov 	word ptr [Dir_Count],0
                mov 	word ptr [File_Count],0
                mov 	word ptr [Total_FSize], 0
                mov 	word ptr [Total_FSize]+2, 0

                mov     ah,0Eh
                mov     bx,07h
                mov     al,0Dh
                int     10h
                mov     al,0Ah
                int     10h
                mov     al,0Dh
                int     10h
                mov     al,0Ah
                int     10h

loc_print_dir_first_file:
 		mov     byte ptr [PrintDir_RowCounter], 16

                mov dx, si
                mov cx, 37h ; File or Directory (S,H,R,A)
                mov ah, 4Eh ; MS Dos Function = Find First File
                int 21h
                jc loc_dir_ok
                 
loc_dfname_use_this:
                mov si, offset DTA_FileName
                mov bx, DTA_Attribute
                mov cl, byte ptr [BX]
                push    cx  
                test    cl, 10h  ; Is it a directory?
                jz      short loc_not_dir

                inc     word ptr [Dir_Count]
                push    si
                mov     cx, 10                   
                mov     si, offset Type_Dir      ; '<DIR>     '
                mov     di, offset Dir_Or_FileSize
                rep     movsb                    ; move 10 bytes
                pop     si

                jmp     short loc_dir_attribute
loc_not_dir:
                inc     word ptr [File_Count]

                mov bx, DTA_FileSize

                mov ax, word ptr [BX]
                mov dx, word ptr [BX]+2

                add     word ptr [Total_FSize], ax
                adc     word ptr [Total_FSize]+2, dx

                mov     di,10 ; 30/10/2010 BugFix 
                        ; (mov di, 9 -> Bug for >=1 GB file size)
                mov     cx, di                  ; 16 bit divisor
loc_dir_rdivide:
                call    Rx_Dos_Div32            ; 32 bit divide
                add     bl, '0'                 ; to make visible
                dec     di
                mov     Byte Ptr [Dir_Or_FileSize][DI],bl
                cmp     ax,0
                ja      short loc_dir_rdivide
                cmp     dx,0
                ja      short loc_dir_rdivide
loc_dir_fill_space:
                cmp     di,0
                jna     short loc_dir_attribute
                dec     di
                mov     Byte Ptr [Dir_Or_FileSize][DI],20h
                jmp     short loc_dir_fill_space
loc_dir_attribute:
                pop     cx
                mov     word ptr [File_Attribute], 2020h
                mov     word ptr [File_Attribute]+2, 2020h
                cmp     cl, 20h  ; Is it an archive file?
                jb      short loc_dir_pass_arch
                mov     Byte Ptr [File_Attribute]+3,'A'
loc_dir_pass_arch:
                and     cl,7
                jz      short loc_dir_file_name
                mov     ch,cl
                and     cl,3
                cmp     ch,cl
                jna     short loc_dir_pass_s
                mov     byte ptr [File_Attribute], 'S'
loc_dir_pass_s:
                and     cl,2
                jz      short loc_dir_pass_h
                mov     byte ptr [File_Attribute]+1, 'H'
loc_dir_pass_h:
                and     ch,1
                jz      short loc_dir_file_name
                mov     byte ptr [File_Attribute]+2, 'R'
loc_dir_file_name:
                mov bx, DTA_Time
                mov dx, word ptr [BX]
                push dx
               ;mov bx, DTA_Time
                mov dx, word ptr [BX]+2 ; DTA_Date
                push    si
                mov  di, offset File_Name
                push di
                mov cx, 12
                mov al, 20h
                rep stosb
                pop di
                push di
                mov cx, 8
loc_dir_file_name_loop_dot:
                lodsb
                cmp al, '.'
                jne short loc_dir_file_name_stosb
                stosb
                loop loc_dir_file_name_loop_dot
loc_dir_file_name_loop: 
                lodsb
                cmp al, '.'
                je short loc_dir_file_name_ext
loc_dir_file_name_stosb:
                stosb
                loop loc_dir_file_name_loop
                inc si 
loc_dir_file_name_ext:                
                pop di
                add di, 9 
                mov cx, 3
loc_dir_file_name_ext_loop: 
                lodsb
                cmp al, 20h
                jna short loc_dir_file_name_ok
                stosb
                loop loc_dir_file_name_ext_loop 
loc_dir_file_name_ok:
                pop     si
                pop bx ; DTA_Time 
Dir_Date_start:
		mov     ax, dx                   ; Date
		and     ax, 00011111b            ; Day Mask
		aam                              ; Q([AL]/10)->AH
						 ; R([AL]/10)->AL
						 ; [AL]+[AH]= Day as BCD
		or      ax, '00'                 ; Convert to ASCII
		xchg    al,ah
                mov     word ptr [File_Day],ax

		mov     ax, dx
		mov     cl, 5
		shr     ax, cl                   ; shift right 5 times
		and     ax, 00001111b            ; Month Mask
		aam
		or      ax, '00'
		xchg    ah,al
                mov     word ptr [File_Month],ax

		mov     ax, dx
		mov     cl, 9
		shr     ax, cl
		and     ax, 01111111b            ; Result = Year - 1980
		add     ax, 1980

		mov     cl, 10
		div     cl                        ; Q -> AL, R -> AH 
		or      ah, '0'
                mov     byte ptr [File_Year]+3,ah

		aam
		xchg    ah, al
		or      ah, '0'                  ; Convert to ASCII
                mov     byte ptr [File_Year]+2,ah

		aam
                xchg    al, ah
		or      ax, '00'
                mov     word ptr [File_Year],ax

Dir_Time_start:
		mov     ax, bx                   ; Time
		mov     cl, 5
		shr     ax, cl                   ; shift right 5 times
		and     ax, 0000111111b          ; Minute Mask
		aam
		or      ax, '00'
		xchg    ah,al
                mov     word ptr [File_Minute],ax

		mov     al, bh                   
		shr     al, 1
		shr     al, 1
		shr     al, 1                    ; ax = hours
		aam
		or      ax, '00'
		xchg    ah, al
                mov     word ptr [File_Hour],ax
loc_show_line:
                mov     si, offset File_Name
                mov     cx, 46
		mov     ah, 0Eh
		mov     bx, 07h
loop_loc_dir_entry:
                lodsb                           
                int     10h                     
                loop    loop_loc_dir_entry  

                mov     al,0Dh
                int     10h
                mov     al,0Ah
                int     10h

                dec     byte ptr [PrintDir_RowCounter]
                jz      Pause_dir_scroll
loc_next_entry:
                mov ah, 4Fh ; MS Dos Function = Find Next File
                int 21h
                jnc loc_dfname_use_this

loc_dir_ok:
                mov     ax, word ptr [Dir_Count]
                mov     di, offset Decimal_Dir_Count
                cmp     ax, 10
                jb      short pass_ddc
                inc     di
                cmp     ax, 100
                jb      short pass_ddc
                inc     di
                cmp     ax, 1000
                jb      short pass_ddc
                inc     di
                cmp     ax, 10000
                jb      short pass_ddc
                inc     di
pass_ddc:
                mov     byte ptr [DI]+1, 0
loc_ddc_rediv:
                xor     dx, dx
                mov     cx, 10
                div     cx
                add     dl, "0"
                mov     byte ptr [DI], dl
                dec     di
                cmp     ax, 0
                ja      short loc_ddc_rediv

                mov     ax, word ptr [File_Count]
                mov     di, offset Decimal_File_Count
                cmp     ax, 10
                jb      short pass_dfc
                inc     di
                cmp     ax, 100
                jb      short pass_dfc
                inc     di
                cmp     ax, 1000
                jb      short pass_dfc
                inc     di
                cmp     ax, 10000
                jb      short pass_dfc
                inc     di
pass_dfc:
                mov     byte ptr [DI]+1, 0
loc_dfc_rediv:
                xor     dx, dx
                mov     cx, 10
                div     cx
                add     dl, "0"
                mov     byte ptr [DI], dl
                dec     di
                cmp     ax, 0
                ja      short loc_dfc_rediv

                mov     di, offset TFS_Dec_End
                mov     byte ptr [DI], 0
                mov     ax, word ptr [Total_FSize]
                mov     dx, word ptr [Total_FSize]+2
                mov     cx, 10
rediv_tfs_hex:
                call    Rx_Dos_Div32
                add     bl, "0"
                dec     di
                mov     byte ptr [DI], bl
                cmp     ax, 0
                ja      short rediv_tfs_hex
                cmp     dx, 0
                ja      short rediv_tfs_hex
                mov     word ptr [TFS_Dec_Begin], di
                mov     si, offset Decimal_File_Count_Header
                call    SINGLIX_PRINTMSG
                mov     si, offset str_files
                call    SINGLIX_PRINTMSG
                mov     si, offset str_dirs
                call    SINGLIX_PRINTMSG
                mov     si, word ptr [TFS_Dec_Begin]
                call    SINGLIX_PRINTMSG
                mov     si, offset str_bytes
                call    SINGLIX_PRINTMSG

                retn

Pause_dir_scroll:
                xor    ah, ah                                           
                int    16h
                cmp    al,1Bh
                je     loc_dir_ok
                mov    byte ptr [PrintDir_RowCounter], 16 ; Reset counter
                jmp    loc_next_entry

PrintDir_RowCounter: db 0

File_Count:     dw 0
Dir_Count:      dw 0
Decimal_File_Count_Header:  db 0Dh, 0Ah
Decimal_File_Count: db 6 dup(0)
str_files:      db " file(s) & "
Decimal_Dir_Count: db 6 dup(0)
str_dirs:       db " directory(s) ", 0Dh, 0Ah, 0
Total_FSize:    dd 0
TFS_Dec_Begin:  dw 0
                db 10 dup(0)
TFS_Dec_End:    db 0
str_bytes:      db " byte(s) in file(s)", 0Dh, 0Ah, 0

proc_print_directory endp


;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Rx_DOS  32 bit Divide                                      ;
; (Special version by Erdogan Tan)                           ;
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - -;
;                                                            ;
; input -> DX_AX = 32 bit dividend                           ;
; input -> CX = 16 bit divisor                               ;
; output -> DX_AX = 32 bit quotient                          ;
; output -> BX = 16 bit remainder                            ;
;                                                            ;
;  This procedure divides the requested 32 bit number        ;
;  and gives the result in DX, AX and BX (remainder)         ;
;                                                            ;
; Original Procedure by Michael Podanoffsky / Real Time DOS  ;
; (c) Erdogan TAN  1999                     [ RXDOSBIO.ASM ] ;
;............................................................;

Rx_Dos_Div32    proc near

		mov  bx, dx
		xchg ax, bx
		xor  dx, dx
		div  cx         ; at first, divide DX
		xchg ax, bx     ; remainder is in DX
				; now, BX has quotient
				; save remainder
		div  cx         ; so, DX_AX divided and
				; AX has quotient
				; DX has remainder
		xchg dx, bx     ; finally, BX has remainder

		retn

Rx_Dos_Div32    endp


;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  data
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

File_Name:
		db  12 dup(20h)
		db  20h
Dir_Or_FileSize:
		db  10 dup(20h)
		db  20h
File_Attribute:
		db  4 dup(20h)
		db  20h
File_Day:
		db  2 dup('0')
		db  '/'
File_Month:
		db  2 dup('0')
		db  '/'
File_Year:
		db  4 dup('0')
		db  20h
File_Hour:
		db  2 dup('0')
		db  ':'
File_Minute:
		db  2 dup('0')
		db  0

Type_Dir:       db '<DIR>     ' 

              
SINGLIXBOOT     ends

                end     START_CODE
