;*****************************************************************************
; TRDOS2.ASM  [ Draft for Kernel TRDOS.COM ]
; (c) 2004-2009  Erdogan TAN  [ 17/01/2004 ]  Last Update: 25/06/2009
; ! Under Development !

; Masterboot / Partition Table at Beginning+1BEh
ptBootable       equ 0
ptBeginHead      equ 1
ptBeginSector    equ 2
ptBeginCylinder  equ 3
ptFileSystemName equ 4
ptEndHead        equ 5
ptEndSector      equ 6
ptEndCylinder    equ 7
ptStartSector    equ 8
ptSectors        equ 12

; Boot Sector Parameters at 7C00h
DataArea1     equ -4
DataArea2     equ -2
BootStart     equ 0h
OemName       equ 03h
BytesPerSec   equ 0Bh
SecPerClust   equ 0Dh
ResSectors    equ 0Eh
FATs          equ 10h
RootDirEnts   equ 11h
Sectors       equ 13h
Media         equ 15h
FATsecs       equ 16h
SecPerTrack   equ 18h
Heads         equ 1Ah 
Hidden1       equ 1Ch
Hidden2       equ 1Eh
HugeSec1      equ 20h
HugeSec2      equ 22h
DriveNumber   equ 24h
Reserved1     equ 25h
bootsignature equ 26h                 
VolumeID      equ 27h
VolumeLabel   equ 2Bh
FileSysType   equ 36h          
Reserved2     equ 3Eh                           ; Starting cluster of P2000

; FAT32 BPB Structure
FAT32_FAT_Size equ 36
FAT32_RootFClust equ 44
FAT32_FSInfoSec equ 48
FAT32_DrvNum equ 64
FAT32_BootSig equ 66
FAT32_VolID equ 67
FAT32_VolLab equ 71
FAT32_FilSysType equ 82

; BIOS Disk Parameters
DPDiskNumber  equ 0h
DPDType       equ 1h
DPReturn      equ 2h
DPHeads       equ 3h
DPCylinders   equ 4h
DPSecPerTrack equ 6h
DPDisks       equ 7h
DPTableOff    equ 8h
DPTableSeg    equ 0Ah
DPNumOfSecs   equ 0Ch

; BIOS INT 13h Extensions (LBA extensions)
; Just After DP Data (DPDiskNumber+)
DAP_PacketSize equ 10h  ; If extensions present, this byte will be >=10h
DAP_Reserved1 equ 11h   ; Reserved Byte 
DAP_NumOfBlocks equ 12h ; Value of this byte must be 0 to 127
DAP_Reserved2 equ 13h   ; Reserved Byte
DAP_Destination equ 14h ; Address of Transfer Buffer as SEGMENT:OFFSET
DAP_LBA_Address equ 18h ; LBA=(C1*H0+H1)*S0+S1-1
                        ; C1= Selected Cylinder Number
                        ; H0= Number Of Heads (Maximum Head Number + 1)
                        ; H1= Selected Head Number
                        ; S0= Maximum Sector Number
                        ; S1= Selected Sector Number
                        ; QUAD WORD
; DAP_Flat_Destination equ 20h ; 64 bit address, if value in 4h is FFFF:FFFFh
                             ; QUAD WORD (Also, value in 0h must be 18h) 
                             ; TR-DOS will not use 64 bit Flat Address

; INT 13h Function 48h "Get Enhanced Disk Drive Parameters"
; Just After DP Data (DPDiskNumber+)
GetDParams_48h equ 20h ; Word. Data Lenght, must be 26 (1Ah) for short data.
GDP_48h_InfoFlag equ 22h ; Word
; Bit 1 = 1 -> The geometry returned in bytes 4-15 is valid.
GDP_48h_NumOfPCyls equ 24h ; Double Word. Number physical cylinders.
GDP_48h_NumOfPHeads equ 28h ; Double Word. Number of physical heads.
GDP_48h_NumOfPSpT equ 2Ch ; Double word. Num of physical sectors per track.
GDP_48h_LBA_Sectors equ 30h ; 8 bytes. Number of physical/LBA sectors.
GDP_48h_BytesPerSec equ 38h ; Word. Number of bytes in a sector.

; TR-DOS Standalone Program Extensions to the DiskParams Block
; Just After DP Data (DPDiskNumber+)
TRDP_CurrentSector equ 3Ah  ; DX:AX (LBA)
TRDP_SectorCount equ 3Eh    ; CX (or Counter)


; DOS Logical Disks
LD_Name equ 0
LD_DiskType equ 1
LD_PhyDrvNo equ 2
LD_FATType equ 3
LD_FSType equ 4
LD_LBAYes equ 5
LD_BPB equ 6
LD_FATBegin equ 96
LD_ROOTBegin equ 100
LD_DATABegin equ 104
LD_StartSector equ 108
LD_TotalSectors equ 112
LD_FreeSectors equ 116
LD_Clusters equ 120
LD_PartitionEntry equ 124
LD_DParamEntry equ 125
LD_MediaChanged equ 126
LD_CDirLevel equ 127
LD_CurrentDirectory equ 128

; Singlix FS Extensions to DOS Logical Disks

LD_FS_Name equ 0
LD_FS_DiskType equ 1
LD_FS_PhyDrvNo equ 2
LD_FS_FATType equ 3
LD_FS_FSType equ 4
LD_FS_LBAYes equ 5
LD_FS_BPB equ 6
LD_FS_BytesPerSec equ 6
LD_FS_MediaAttrib equ 8
LD_FS_VersionMajor equ 9
LD_FS_SecPerTrack equ 10
LD_FS_NumHeads equ 11
LD_FS_DATLocation equ 12
LD_FS_DATSectors equ 16
LD_FS_UnDelDirD equ 20
LD_FS_CDIR_Buffer equ 24
LD_FS_VolumeSerial equ 28
LD_FS_VolumeName equ 32
LD_FS_MATLocation equ 96
LD_FS_RootDirD equ 100
LD_FS_FirstFreeSector equ 104
LD_FS_BeginSector equ 108
LD_FS_VolumeSize equ 112
LD_FS_FreeSectors equ 116
LD_FS_CDIR_DDT equ 120
LD_FS_PartitionEntry equ 124
LD_FS_DParamEntry equ 125
LD_FS_MediaChanged equ 126
LD_FS_CDirLevel equ 127
LD_FS_CDIR_Converted equ 128

; Valid FAT Types
FS_FAT12 equ 1
FS_FAT16_CHS equ 2
FS_FAT32_CHS equ 3
FS_FAT16_LBA equ 4
FS_FAT32_LBA equ 5

; Cursor Location
CCCpointer equ  0450h   ; BIOS data, current cursor column
; FAT Clusters EOC sign
FAT12EOC equ 0FFFh
FAT16EOC equ 0FFFFh
;FAT32EOC equ 0FFFFFFFh ; It is not direct usable for 8086 code
; BAD Cluster
FAT12BADC equ 0FF7h
FAT16BADC equ 0FFF7h
;FAT32BADC equ 0FFFFFF7h ; It is not direct usable for 8086 code
; MS-DOS FAT16 FS (Maximum Possible) Last Cluster Number= 0FFF6h 


Present segment Para 'code'

		assume CS:Present, DS:Present, ES:Present, SS:Present


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±
;±              PROCEDURE proc_start
;±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

proc_start      proc    far

                org 100h
start:                                         
                cmp ax, 417
                jne short pass_trdos_boot_sector
                mov byte ptr [Boot_Disk], dl
loc_NOP:        db 90h                
pass_trdos_boot_sector:
                mov si, offset Starting_Msg
                call proc_printmsg

                call proc_memory_init ; MEM_INIT.ASM

  		mov ax, es
                sub ax, 10h
                mov es, ax  ; Move to 100h backward

                cli
                mov sp, KERNEL_FILESIZE+200h ; 100h bytes reserved for stack
                mov ss, ax
                sti

    		push es     		     ; ES:100h is beginning of the kernel
                mov si, offset retf_from_memory_init
                push si 

                mov ds, ax

                retf

retf_from_memory_init:

                call proc_drv_init  ; DRV_INIT.ASM

  		xor dl, dl
                call floppy_drv_init
                jc short pass_print_volumeinfo_fd0

                mov si, Offset Logical_DosDisks
                cmp byte ptr [SI], 'A'
                jb short jmp_to_pv_int16h
                
                call proc_print_volume_info

pass_print_volumeinfo_fd0:                
 		mov dl, 1
                call floppy_drv_init
                jc short loc_print_volumeinfo_hd
		mov si, offset Logical_DOSDisks 
                add si, 100h
		cmp byte ptr [SI], 'A'
                jb short jmp_to_pv_int16h
                
                call proc_print_volume_info
 
loc_print_volumeinfo_hd:
                add si, 100h
                
                cmp byte ptr [SI], 'C'
                jb short jmp_to_pv_int16h

                call proc_print_volume_info

                jmp short loc_print_volumeinfo_hd
                 
jmp_to_pv_int16h:
		mov si, offset Msg_CRLF_temp
                call proc_printmsg
                mov si, Program_Version
                call proc_printmsg
                xor ah, ah
                int 16h
                int 19h

msg_CRLF_temp:
                db 7, 0Dh, 0Ah, 0

proc_start      endp

proc_printmsg   proc near

               ; mov AH, 0Fh ; Get Video Display Mode
               ; int 10h
                ;AH= Number of columns
                ;AL= Video mode
                ;BH= Current video page
              ;  mov BL, byte ptr [Program_CharColorAtr]
                 mov BX, 07h
loc_print:
		lodsb                           ; Load byte at DS:SI to AL
		and     AL,AL            
		je      short loc_return        ; If AL = 00h then return
		mov     AH,0Eh                  
		int     10h                     ; BIOS Service func ( ah ) = 0Eh
						; Write char as TTY
						;AL-char BH-page BL-color
		jmp     short loc_print           
loc_return:
		retn

Program_CharColorAtr: db 0

proc_printmsg   endp

proc_clear_screen proc near

                mov ah, 0Fh 
                int 10h
                mov ah, 0
                int 10h

                retn

proc_clear_screen 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

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; From binary (byte) to hexadecimal (character) converter    ;
;                                                            ;
; input -> AL = byte (binary number) to be converted         ;
; output -> AH = First character of hexadecimal number       ;
; output -> AL = Second character of hexadecimal number      ;
;                                                            ;
; (c) Erdogan TAN  1998 - 1999                               ;
;............................................................;

; 1998

proc_hex        proc    near

		db 0D4h,10h                     ; Undocumented inst. AAM
						; AH = AL / 10h
						; AL = AL MOD 10h
		or AX,'00'                      ; Make it ZERO (ASCII) based

                xchg AH,AL 

; 1999
		cmp AL,'9'
		jna pass_cc_al
		add AL,7
pass_cc_al:
		cmp AH,'9'
		jna pass_cc_ah
		add AH,7
pass_cc_ah:

; 1998
		retn

proc_hex        endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; 32 bit Multiply                                            ;
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - -;
;                                                            ;
; input -> DX_AX = 32 bit multiplier                         ;
; input -> BX = 16 bit number to be multiplied by DX_AX      ;
; output -> BX_DX_AX = 48 bit (16+32 bit) result number      ;
;                                                            ;
; (c) Erdogan TAN  1999                                      ;
;............................................................;

proc_mul32    proc near

	      push cx

	      mov cx, bx
	      mov bx, dx

	      mul cx

              xchg ax, bx

	      push dx

              mul cx 

              pop cx 

              add ax, cx 
	      adc dx, 0

	      xchg bx, ax
	      xchg dx, bx

	      pop cx

	      retn

proc_mul32    endp

INCLUDE MEM_INIT.ASM   ; TRDOS Memory Initialization Procedures

INCLUDE DRV_INIT2.ASM  ; TRDOS Drive Initialization Procedures

INCLUDE DISK_IO.ASM    ; TRDOS Disk Read/Write Procedures

INCLUDE DRV_FAT.ASM    ; TRDOS FAT 12-16-32 FS Procedures

proc_print_volume_info proc near
                ; INPUT DS:SI = TRDOS Drive Parameters Table
                mov al, byte ptr [SI]
               ;cmp al,'A'  
               ;jnb short pass_vol_drv_name_check
               ;retn
;pass_vol_drv_name_check:
                push si
                mov byte ptr [Vol_Drv_Name], al
               
                mov cx, 32
                mov di, offset Vol_Vol_Name
                push di
                mov ax, 2020h
                rep stosw 
                pop di
 
                cmp byte ptr [SI][LD_FATType], 0
                ja short loc_pass_mov_vol_name_0
                add si, LD_FS_VolumeName
                mov cx, 64
                jmp short loc_vol_move_volume_name
loc_pass_mov_vol_name_0:
                mov cx, 11  
                cmp byte ptr [SI][LD_FATType], 2
                ja short loc_pass_mov_vol_name_2
                add si, LD_BPB+VolumeLabel
                jmp short loc_vol_move_volume_name
loc_pass_mov_vol_name_2:
                add si, LD_BPB+FAT32_VolLab
loc_vol_move_volume_name:
                lodsb
                test al, al
                jz short pass_vol_move_volume_name 
                stosb
                loop loc_vol_move_volume_name
pass_vol_move_volume_name:
                pop si
                push si
                cmp byte ptr [SI][LD_FATType], 0
                ja short loc_pass_mov_vol_size
                mov ax, word ptr [SI][LD_FS_VolumeSize]
                mov dx, word ptr [SI][LD_FS_VolumeSize]+2
                mov bx, word ptr [SI][LD_FS_BytesPerSec]
                cmp dx, 127
                ja short pass_vol_size_bytes_calc
                jmp short loc_vol_size_mul32
loc_pass_mov_vol_size:
                mov ax, word ptr [SI][LD_TotalSectors]
                mov dx, word ptr [SI][LD_TotalSectors]+2
                mov bx, word ptr [SI][LD_BPB][BytesPerSec]
                cmp byte ptr [SI][LD_FATType],2
                ja short pass_vol_size_bytes_calc
                ; cmp dx, 127
              ; ja short pass_vol_size_bytes_calc
                jmp short loc_vol_size_mul32
pass_vol_size_bytes_calc:
                mov cx, offset VolSize_KiloBytes
                mov word ptr [VolSize_Unit], cx 
                cmp bx, 1024
                jnb short loc_vol_ax_div_bx
              ;  push ax
              ;  push dx
              ;  xor dx, dx
              ;  mov ax, 1024
              ;  div bx
              ;  mov cx, ax
              ;  pop dx
              ;  pop ax
                mov cx, 2
                call Rx_Dos_Div32
                jmp short pass_volsize_overflow
loc_vol_ax_div_bx:
              ;  push ax
              ;  push dx
              ;  xor dx, dx
              ;  mov ax, 1024
              ;  xchg ax, bx
              ;  div bx
              ;  mov bx, ax
              ;  pop dx
              ;  pop ax
                mov bx, 2
loc_vol_size_mul32:
                call Proc_Mul32
                mov cx, offset VolSize_Bytes
                mov word ptr [VolSize_Unit], cx   
pass_volsize_overflow:
                mov di, offset Vol_Tot_Sec_Str_End
              ; mov byte ptr [DI], 0
                mov cx, 10
loc_vol_div32_1_again:
                call Rx_Dos_Div32
                add bl, '0'
                dec di
                mov byte ptr [DI], bl
                test ax, ax
                jnz short loc_vol_div32_1_again
                test dx, dx
                jnz short loc_vol_div32_1_again

                mov word ptr [Vol_Tot_Sec_Str_Start], DI

                cmp byte ptr [SI][LD_FATType], 0
                ja short loc_write_vol_FAT_str
                mov di, offset Vol_FS_Name
                mov word ptr [DI], 'RT'
                inc di
		inc di
                mov word ptr [DI], 'F '
                inc di
                inc di
                mov word ptr [DI], '1S'
                jmp short pass_write_vol_FS_str_1
loc_write_vol_FAT_str:
                mov di, offset Vol_FS_Name
                mov word ptr [DI], 'AF'
                inc di
		inc di
                mov word ptr [DI], ' T'
                inc di
                inc di
                mov ax, '21'
                cmp byte ptr [SI][LD_FATType], 1
                jna short pass_write_vol_FS_str_0
                mov ax, '61'
 		cmp byte ptr [SI][LD_FATType], 2
                jna short pass_write_vol_FS_str_0
                mov ax, '23'
pass_write_vol_FS_str_0:
                mov word ptr [DI], ax 
pass_write_vol_FS_str_1:
                mov ax, word ptr [SI][LD_FreeSectors]
                mov dx, word ptr [SI][LD_FreeSectors]+2

                cmp dx, 127
                jna short loc_vol_freespace_mul32
pass_vol_freespace_bytes_calc:
                mov cx, offset VolSize_KiloBytes
                mov word ptr [VolSize_Unit], cx 
                cmp bx, 1024
                jnb short loc_vol_freespace_ax_div_bx
              ;  push ax
              ;  push dx
              ;  xor dx, dx
              ;  mov ax, 1024
              ;  div bx
              ;  mov cx, ax
              ;  pop dx
              ;  pop ax
                mov cx, 2
                call Rx_Dos_Div32
                jmp short pass_vol_freespace_overflow
loc_vol_freespace_ax_div_bx:
              ;  push ax
              ;  push dx
              ;  xor dx, dx
              ;  mov ax, 1024
              ;  xchg ax, bx
              ;  div bx
              ;  mov bx, ax
              ;  pop dx
              ;  pop ax
                mov bx, 2
loc_vol_freespace_mul32:
                call Proc_Mul32
                mov cx, offset VolSize_Bytes
                mov word ptr [VolSize_Unit], cx   
pass_vol_freespace_overflow:
 
                mov di, offset Vol_Free_Sectors_Str_End
              ; mov byte ptr [DI], 0
                mov cx, 10
loc_vol_div32_2_again:
                call Rx_Dos_Div32
                add bl, '0'
                dec di
                mov byte ptr [DI], bl
                test ax, ax
                jnz short loc_vol_div32_2_again
                test dx, dx
                jnz short loc_vol_div32_2_again

                mov word ptr [Vol_Free_Sectors_Str_Start], DI

                mov si, offset Volume_in_drive
                call proc_printmsg

                mov si, offset Vol_Total_Sector_Header
                call proc_printmsg
                mov si, word ptr [Vol_Tot_Sec_Str_Start]
                call proc_printmsg
                mov si, word ptr [VolSize_Unit]
                call proc_printmsg

                mov si, offset Vol_Free_Sectors_Header
                call proc_printmsg
                mov si, word ptr [Vol_Free_Sectors_Str_Start]
                call proc_printmsg
                mov si, offset VolSize_Bytes
                call proc_printmsg

                pop si
                retn

FreeClusterCount: dd 0
Vol_Free_Sectors_Str_Start: dw 0
Vol_Free_Sectors_Str: db 10 dup(0)
Vol_Free_Sectors_Str_End: db 0
Vol_Free_Sectors_Header:
                db "Free Space  : ", 0
Vol_Tot_Sec_Str_Start: dw 0
Vol_Tot_Sec_Str: db 10 dup(0)
Vol_Tot_Sec_Str_End: db 0
Vol_Total_Sector_Header:
                db 0Dh, 0Ah, "Volume Size : ", 0
VolSize_Unit:   dw 0
VolSize_KiloBytes: db " kilobytes", 0Dh, 0Ah, 0
VolSize_Bytes:  db " bytes", 0Dh, 0Ah, 0
Volume_in_drive:
                db 0Dh, 0Ah
Vol_FS_Name:    db "TR FS1 "
                db "Volume in drive "
Vol_Drv_Name:   db 30h
                db ":"
                db " is "
                db 0Dh, 0Ah
Vol_Vol_Name:   db 64 dup (20h)
                db 0Dh, 0Ah, 0

proc_print_volume_info endp

Starting_Msg:
                db 0Dh, 0Ah 
                db "Starting TRDOS ..."
                db 0Dh, 0Ah, 0
Magic_Bytes:
                   db 4
                   db 1
Program_Version:
                   db 7
                   db "[TRDOS] Main Program v1.0.250609"
                   db 0Dh, 0Ah
                   db "(c) Erdogan Tan 2005-2009"
                   db 0Dh, 0Ah, 0

Logical_DOSDisks:  dw 3328 dup(0)

End_Of_Run_Buffer: db 0

BOOT_DISK: db 0
FAT12_Buffer: dw 0  ; Pointer for FAT12 Buffer Segment (9 sectors)
KERNEL_FILESIZE equ $-100h

Present            ends

                   end  start
