; ****************************************************************************
; Turkish Rational SINGLIX  
; Disk Operation System v1.0 Project
; 1.44 MB Floppy Disk to Image File Code
;
; Copyright (C) Erdogan TAN - 06/08/2011
;
;
; ****************************************************************************

; DTA (PSP+80h= Offset 128)
DTA_FileName equ 158 ; PSP + 30

.8086

SINGLIXBOOT     SEGMENT PUBLIC 'CODE'
                assume cs:SINGLIXBOOT,ds:SINGLIXBOOT,es:SINGLIXBOOT,ss:SINGLIXBOOT

                org 100h

START_CODE:

proc_start      proc near

                mov bx, SizeOfFile+100
                add bx, 15
                shr bx, 1
        	shr bx, 1
		shr bx, 1
		shr bx, 1
                mov ah, 4Ah ; modify memory allocation
               ;push cs
               ;pop es
                int 21h 
                                  
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; see if drive specified
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              
                mov si, 80h                     	; PSP command tail
                mov cl, byte ptr [SI]
                or cl, cl                               
                jnz short READSTUB_02           	; jump if not zero

READSTUB_01:
                mov si, offset SINGLIX_Welcome
                call SINGLIX_PRINTMSG
                jmp READSTUB_25

READSTUB_02:
                inc si
                mov dx, word ptr [SI]
                cmp dl, " "                      	; is it SPACE ?
                jne short READSTUB_03

                dec cl                                  
                jnz short READSTUB_02             
                jmp short READSTUB_01

READSTUB_03:
                cmp dl, "f"
                jne READSTUB_04
                cmp dh, "d"
                jne READSTUB_01
                mov dx, word ptr [SI]+2
                cmp dh, ":"
                jne short READSTUB_01
                cmp dl, "0"                            
                jb READSTUB_01
                cmp dl, "1"
                ja READSTUB_01
                sub dl, "0"
                add si, 4 
                jmp short READSTUB_06
               
READSTUB_04:
                cmp dh, ":"
                jne short READSTUB_01    
                cmp dl, "A"
                jb  short READSTUB_01
                cmp dl, "B"	                        ; A - B
                jna short READSTUB_05                    
                cmp dl, "a"                             ; a - b
                jb  short READSTUB_01                  
                cmp dl, "b"                         
                ja  short READSTUB_01                 
                sub dl, "a"-"A"	      
READSTUB_05:
                sub dl, "A"
                add si, 2
READSTUB_06:
                mov byte ptr [Drive_Number], dl
                mov ah, 08h
                int 13h
                ; ES <> DS
                jc READSTUB_26
               
                cmp dl, byte ptr [Drive_Number] ; 03/08/2011
                jna READSTUB_26

                cmp bl, 04h
                jnb short READSTUB_07

                mov si, offset msg_Drive_Not_Compatible
                call SINGLIX_PRINTMSG

                jmp READSTUB_25


;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Write message
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

READSTUB_07:
                push ds
                pop es
                mov di, offset Image_File_Name
READSTUB_08:
                lodsb
                cmp al, 20h
                jb READSTUB_01
                je short READSTUB_08
                mov cx, 64 
READSTUB_09:
                stosb
                lodsb
                cmp al, 20h 
                jna short READSTUB_10
                loop READSTUB_09
READSTUB_10:  
                mov dx, offset Image_File_Name
                mov cx, 27h ; File Attributes
                mov ah, 4Eh ; MS Dos Function = Find First File
                int 21h
                jnc short READSTUB_12

READSTUB_11:    
               ;mov dx, offset Image_File_Name
                xor cx, cx ; File Attribute = 0
                mov ah, 3Ch ; MS Dos Function = Create File
                int 21h
                jnc short READSTUB_18

                mov si, offset msg_bad_file_name
                call SINGLIX_PRINTMSG
                jmp READSTUB_25

READSTUB_12:
                mov si, offset Msg_DoYouWantOverWrite
                call SINGLIX_PRINTMSG

                mov si, offset DTA_FileName
                call SINGLIX_PRINTMSG

		mov si, offset msg_yes_no
                call SINGLIX_PRINTMSG
READSTUB_13:
                xor ax, ax
                int 16h                                 ; wait for keyboard command
                cmp al, "C"-40h
                je READSTUB_24                   
                cmp al, 27
                je short READSTUB_15_C1
READSTUB_14:
                and al, 0DFh
                cmp al, "Y"                             ; Yes?
                je short READSTUB_15_Y                  ; write
                cmp al, "N"                             ; No?
                jne short READSTUB_13                

READSTUB_15_N:
                mov si, offset msg_NO
READSTUB_15_C2:
                call SINGLIX_PRINTMSG
                jmp READSTUB_25
READSTUB_15_C1:
                mov si, offset msg_cancel
                jmp short READSTUB_15_C2
              
READSTUB_15_Y:
                mov si, offset msg_YES
                call SINGLIX_PRINTMSG
READSTUB_16:
                mov si, offset SINGLIX_CRLF
                call SINGLIX_PRINTMSG

READSTUB_17:
                mov dx, offset Image_File_name
                mov ah, 3Dh ; MS Dos Function = Open File
                mov al, 1 ; File opened for writing
                int 21h
                jc short READSTUB_26

READSTUB_18:
		mov word ptr [FileHandle], ax

                mov si, offset Msg_writing_if
                call SINGLIX_PRINTMSG

READSTUB_19:  
  		mov AH, 3
                xor BH, BH
                int 10h ; Return Cursor Position
                ; DL = Column, DH= Line
                mov word ptr [Cursor_Pos], DX
                mov word ptr [Cursor_Type], CX

                mov AX, word ptr [FD_Sector]
READSTUB_20: 
                push AX
                inc AX 
                mov SI, offset Sector_Str
                call proc_bin_to_decimal
                pop AX
                mov BX, offset SECBUFFER
                call proc_read_fd_sector
                jc short READSTUB_26

READSTUB_21: 
                mov ah, 40h ; Write File
                mov cx, 512
                mov dx, offset SECBUFFER
                mov bx, word ptr [FileHandle]
                int 21h
                jc short READSTUB_24

READSTUB_22:    
                mov AX, word ptr [FD_Sector]        
                cmp AX, 2879
                jnb short READSTUB_23
                inc AX
                mov word ptr [FD_Sector], AX
                jmp short READSTUB_20

READSTUB_23:        
                mov si, offset Msg_OK
                call SINGLIX_PRINTMSG

READSTUB_24:
                mov ah, 3Eh ; Close File
                mov bx, word ptr [FileHandle]
                int 21h
READSTUB_25:
                mov si, offset SINGLIX_CRLF
                call SINGLIX_PRINTMSG

                int 20h
                
                int 19h 

READSTUB_26:
                mov si, offset msg_singlix_drv_read_error
                call SINGLIX_PRINTMSG

                cmp byte ptr [FileHandle], 0
                ja short READSTUB_24

                jmp short READSTUB_25

proc_start     endp

Drive_Number: db 0
FileHandle: dw 0
FD_Sector: dw 0 
Cursor_Pos: dw 0
Cursor_Type: dw 0
Error_Code: db 0

proc_read_fd_sector    proc near
                ; Only for 1.44 MB FAT12 Floppy Disks
                ; INPUT -> AX = Logical Block Address
                ; ES:BX = Sector Buffer
                ; OUTPUT -> clc or stc
                ; CLC -> AX = Logical Block Address
                ; STC -> DX = Logical Block Address
                ; STC -> AH = Error Number
                mov     CX, 7  ; Retry Count
loc_read_fd_chs:
                push    AX                      ; Linear sector number
                push    CX                      
                mov     DX, 18                  ; Sectors per Track
                div     DL
                mov     CL, AH                  ; Sector (zero based)
                inc     CL                      ; To make it 1 based
                shr     AL, 1                   ; Convert Track to Cylinder
                adc     DH, 0                   ; Head (0 or 1)
                mov     DL, Byte Ptr [Drive_Number]
                mov     CH,AL                   
                mov     AX,0201h
                int     13h                     ; BIOS Service func ( ah ) = 3
                                                ; Write disk sectors
               ; mov     byte ptr [Error_Code], ah
                pop     CX
                pop     AX

                jnc     short pass_read_fd_chs_error
                loop    loc_read_fd_chs
               ; mov     DX, AX
               ; mov     ah, byte ptr [Error_Code]
                stc
pass_read_fd_chs_error:
                retn

proc_read_fd_sector    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_bin_to_decimal proc near
               ; 3-8-2011
               ; 1-3-2005, 25-5-2009
               ;  Erdogan Tan
               ; INPUT: DS:SI = Target location (last digit)
               ;        AX= Binary Number (Integer)
               ; OUTPUT: Decimal char at DS:SI
               ; SI decremented after every division
               ; till AX<10.
               ; CX, DX will be changed.

               push si
               add si, 3
               mov cx, 10
loc_btd_re_divide:
               xor dx, dx
               div cx
               add dl, '0'
               mov byte ptr [SI], dl
               cmp ax, 0
               jna short print_decimal_sector_number
               dec si
               jmp short loc_btd_re_divide

print_decimal_sector_number:
               ; 23/05/2009
                mov ah, 1                      ; Set Cursor Type 
                mov ch, 20h                    ; Disable cursor  
                int 10h          
                mov ah, 2                      ; Set Cursor Position    
                mov dx, word ptr [Cursor_Pos]
                xor bh, bh
                int 10h  ; Set Cursor Position             
                pop si
               ;mov si, offset Sector_Str
                call SINGLIX_PRINTMSG
                mov ah, 1                      ; Set Cursor Type 
                mov cx, word ptr [Cursor_Type]  
                int 10h  

                retn

;Str_Number_Input: dw 0

proc_bin_to_decimal endp

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  messages
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

SINGLIX_Welcome:
                db 0Dh, 0Ah
                db "TR-DOS 1.44 MB Floppy Disk Image File Make Utility"
                db 0Dh, 0Ah
                db "v1.0.060811  (c) Erdogan TAN 2011"
                db 0Dh,0Ah
                db 0Dh,0Ah
                db "Usage: fdread [Drive] <ImageFileName>"
                db 0Dh,0Ah
                db 0Dh,0Ah
                db "Drive names:"
                db 0Dh,0Ah
                db 0Dh,0Ah
                db "fd0 (Floppy Disk 1, A:)", 0Dh, 0Ah
                db "fd1 (Floppy Disk 2, B:)", 0Dh, 0Ah
 		db 0Dh,0Ah
                db "Samples:"
                db 0Dh,0Ah
                db 0Dh,0Ah
                db "fdread A: A.IMG", 0Dh, 0Ah
                db "fdread fd0: fd0.img", 0Dh, 0Ah
                db 0

Msg_DoYouWantOverWrite:
                db 07h
                db 0Dh, 0Ah
                db "Do you want to overwrite file "
                db 0
msg_yes_no:
                db " (Yes/No)? ", 0

SINGLIX_FD_Name:
                db "fd"
SINGLIX_FD_Number:
                db "0: ", 0

Msg_writing_if:
                db 0Dh, 0Ah
                db "Reading sector: ", 0

Sector_Str:     db "0000", 0

str_Image_File_Name:
                db 13 dup(0)

Msg_OK:
                db " OK.", 0

msg_YES:        db " YES"
                db 0
msg_NO:         db " NO"
                db 0   

msg_Cancel:     db " CANCEL"
                db 0   

SINGLIX_CRLF:
                db 0Dh, 0Ah, 0

msg_singlix_drv_read_error:
                db 0Dh, 0Ah
                db "Drive not ready or read error !"
                db 0

msg_bad_file_name:
  		db 0Dh, 0Ah
                db "Bad file name !"
                db 0

msg_Drive_Not_Compatible:
                db 0Dh, 0Ah
                db "Drive not compatible with 1.44 MB floppy disk !"
                db 0

fdwrite_CopyRight:
                db  "(c) Erdogan TAN - 06/08/2011"

SECBUFFER:      db 512 dup(0)

image_file_name: db 66 dup(0) 

SizeOfFile      equ $-100

               
SINGLIXBOOT     ends

                end     START_CODE
