; *****************************************************************************
;
; TRIO.ASM  [ WINTRIO.ASM ]
;
; Turkish Rational's
; (MS-DOS 6.2 Clone) Disk Operation System v1.0 Project
; TR-DOS Executer Operation System Startup File for Windows 95/98 boot sector.
; [ attrib -s -h -r a:\IO.SYS ->
; rename a:\IO.SYS a:\GO.SYS ->
; masm trio ->
; link /t trio ->
; copy trio.com a:\IO.SYS ]
; Copyright (C) 2000  Erdogan TAN  [ 16/03/2000 ]  Last Update: 14/06/2004
;
; *****************************************************************************

; 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

Present segment Para 'code'

		assume CS:Present, DS:Present, ES:Present, SS:Present


;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;              PROCEDURE proc_start
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

proc_start      proc    near

start:                                         
                db 'MZ'
wait_seconds:   dw 01A1h

Msg_Trio_Version:
                db 0Dh, 0Ah
                db "TR-DOS Startup File for WINDOWS 4 [ TRIO.SYS Version W4.1.0 ]"
                db 0Dh, 0Ah
                db "[ (c) Erdogan Tan - 2004 ]"
                db 0Dh, 0Ah, 0
                db 1 dup (0)

                org 100h
Starting_Msg:
                db 0Dh, 0Ah
                db "Loading Kernel TRDOS... ", 0

                db 1 dup (0)

                org 200h

                inc dx
                dec dx

                push cs
                pop  ds

                mov bp, 7C00h    ; ( SS = 0  )

                mov si, offset Starting_Msg
                call proc_printmsg

                mov ah, 02h
                int 1Ah
                mov byte ptr [wait_seconds], dh
                jc short pass_delay_loop
delay_loop:
                mov ah, 11h
                int 16h
                jnz short loc_get_char

                mov ah, 02h
                int 1Ah

                cmp dh, byte ptr [wait_seconds]
                je  short delay_loop

pass_delay_loop:
                mov ah, 11h
                int 16h
                jz short load_run_time_system
loc_get_char:
                mov ah, 10h
                int 16h
                or al, al
                jz short load_run_time_system
                cmp al, 1Bh
                jnz short load_run_time_system
                mov si, offset Msg_Trio_Version
                call proc_printmsg

                xor ah, ah
                int 16h

                jmp short load_ms_windows

load_run_time_system:
                 
                mov si, offset nextline
                call proc_printmsg

                call proc_loadrootdir
                jc short load_ms_windows

                call proc_find_file
                cmp bx, 2
                jb short load_ms_windows

                mov word ptr [Destination], 8100h
                mov ax, bx
loc_load_next_cluster:
                mov word ptr [FAT_CurrentCluster], ax
                mov bx, word ptr [Destination]

		dec     AX
		dec     AX
                xor     CH,CH
                mov     CL,Byte Ptr [bp][SecPerClust]

                push    ax
                mov     ax, word ptr [bp][BytesPerSec]
                mul     cx
                add     word ptr [Destination], ax
                pop     ax

                mul     CX
                add     AX,Word Ptr [bp][DataArea1]
                adc     DX,Word Ptr [bp][DataArea2]
						; Linear address of the cluster
                call    proc_read
                jc      short loc_failed

                mov     ax, word ptr [FAT_CurrentCluster]
                call    proc_get_next_cluster
                jc      short loc_failed
                cmp     al, 0F0h
                jb      short loc_load_next_cluster
                cmp     byte ptr [bp][DriveNumber], 80h
                jnb     short pass_fat12_eoc_check
                cmp     ah, 0Fh
                jb      short loc_load_next_cluster
                jmp     short pass_fat16_eoc_check
pass_fat12_eoc_check:
                cmp     ah, 0FFh
                jb      short loc_load_next_cluster
pass_fat16_eoc_check:
                mov     bx, 800h
                mov     ds, bx
                mov     es, bx
                mov     ss, bx
                mov     sp, 0FFFFh
                jmp     dword ptr CS:[trio_offset]
loc_failed:
                mov     SI, offset trfailedmsg
		call    proc_printmsg
loc_retry:
		xor     AX,AX
                int     16h   

                int     19h                     ; Reboot

Destination:    dw 0

load_ms_windows:
                mov si, offset nextline
                call proc_printmsg

                xor si, si
                mov ds, si

                mov si, 7DD8h       ; "I" address of "IO.SYS"
                dec byte ptr [SI]   ; Convert JO.SYS to IO.SYS or
                dec byte ptr [SI]   ; IO.SYS to GO.SYS

                jmp dword ptr CS:[win_boot_addr]

proc_start      endp

proc_printmsg   proc near
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                  
		mov     BX,07h             
		int     10h                     ; BIOS Service func ( ah ) = 0Eh
						; Write char as TTY
						;AL-char BH-page BL-color
		jmp     short loc_print           
loc_return:
		retn

proc_printmsg   endp

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;              PROCEDURE proc_read
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

proc_read       proc    near                    ; FAT/FILE Transfer Procedure

		mov     Byte Ptr [RetryCount],04h
loop_loc_14:
		push    CX                      ; # of FAT/FILE/DIR sectors
		push    AX                      ; Linear sector #
		push    DX                      ; DX_AX = Linear address (sectors)
                mov     CX,Word Ptr [bp][SecPerTrack]
                push    BX
		call    RX_DOS_DIV32            ; Special 32 bit divide !!!
						; To fix large disk problem.
						; After division, DX must
						; contain high word part of
						; number of track.
						; Example : 63 sectors/track
						; max. possible track no.
						; without this bugfix = FFFFh
						; (AX) and DX is remain.
						; Max. possible sector number
                                                ; to read = FFFFh * 63.
						; After bugfix, it is
						; FFFFFFFFh
						; (c) Erdogan Tan 1999
						; (October 20th, 1999)
		
                mov     CX, BX                  ; Sector (zero based)
                inc     CX                      ; To make it 1 based
		push    CX
                mov     CX,Word Ptr [bp][Heads]
		call    RX_DOS_DIV32            ; Convert track to head & cyl
                mov     DH, BL                  ; BX = Head (max. FFh)
		pop     CX
						; AX=Cyl, DH=Head, CX=Sector
                pop     BX                      ; ES:BX = Buffer

                mov     DL,Byte Ptr [bp][DriveNumber]
		mov     CH,AL                   
		ror     AH,1                    ; Rotate right
		ror     AH,1                   
		or      CL,AH                   
		mov     AX,0201h
		int     13h                     ; BIOS Service func ( ah ) = 2
						; Read disk sectors
						;AL-sec num CH-track CL-sec
						; DH-head DL-drive ES:BX-buffer
						;CF-flag AH-stat AL-sec read
						; If CF = 1 then (If AH > 0)
		jnc     short pass_hex          ; error code in AH
		xchg    AH,AL                   ; now it is in AL
		call    proc_hex                ; Makes error code to visible
		mov     Word Ptr [Register_AX],AX
		stc                             ; Set carry flag, again
pass_hex:
		pop     DX
		pop     AX
		pop     CX
		jc      short loc_16
                add     AX,1
                adc     DX,0    
		jc      short loc_17                 
loc_15:
                add     BX,Word Ptr [bp][BytesPerSec]

                loop    loop_loc_14             ; Loop if CX > 0

		retn
loc_16:
		dec     Byte Ptr [RetryCount]
		jnz     short loop_loc_14
loc_17:
		retn

proc_read       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


proc_loadrootdir        proc near
                mov     AL,Byte Ptr [bp][FATs]  ; 10h = Number of FATs
		cbw                             
                mul     Word Ptr [bp][FATsecs]  ; 16h = # of FAT sectors
                add     AX,Word Ptr [bp][Hidden1]
                adc     DX,Word Ptr [bp][Hidden2]
                add     AX,Word Ptr [bp][ResSectors]
		adc     DX,0                    

                mov     Word Ptr [bp][DataArea1],AX
                mov     Word Ptr [bp][DataArea2],DX

		push    AX
		push    DX

		mov     AX,20h                  ; Size of a directory entry
                mov     CX,Word Ptr [bp][RootDirEnts]
		mul     CX
                mov     BX,Word Ptr [bp][BytesPerSec]
		add     AX,BX                   ; Round up
		dec     AX                      
		div     BX                      
                add     Word Ptr [bp][DataArea1],AX ; Location of the 1st data cluster
                adc     Word Ptr [bp][DataArea2],0         

						; AX = Total sectors of root directory
		mov     cx,ax

                xor     BX,BX                   ; Root directory buffer segment
		mov     ES,BX
                mov     BX,8000h

		pop     DX                      ; DX_AX = Location of root directory
		pop     AX

                call proc_read

                retn

proc_loadrootdir        endp

proc_get_next_cluster   proc near
                ; INPUT -> AX = Cluster Number, 16 bit
                ; OUTPUT -> clc -> No Error
                ; AX: Next Cluster Number, 16 bit
                ; stc -> Error
              ; mov word ptr [FAT_CurrentCluster], ax
                xor dx, dx
              ; mov es, dx
                mov di, 7000h  ; [FAT_Buffer]
check_next_cluster_fat_type:
                cmp byte ptr [bp][DriveNumber], 80h
                jb short get_FAT12_next_cluster
get_FAT16_next_cluster:
                mov bx, 300h ;768
                div bx
                ; AX = Count of 3 FAT sectors
                ; DX = Sector Offset
                shl dx, 1 ; Multiply by 2
                push dx
                mov bx, 3
                mul bx  
                pop bx ; Sector Offset
                ; AX = FAT Sector
                ; DX = 0
                cmp ax, word ptr [FAT_BufferSector]
                jne load_FAT_sectors
                mov ax, word ptr ES:[DI][BX]
                retn
get_FAT12_next_cluster:
                mov bx, 400h ;1024
                div bx
                ; AX = Count of 3 FAT sectors
                ; DX = Buffer Entry Offset
                push ax
                mov ax, 3
                mul dx    ; Multiply by 3
                shr ax, 1 ; Divide by 2
                mov dx, ax
                pop ax
                push dx
                mov bx, 3
                mul bx  
                pop bx ; Buffer Byte Offset
                ; AX = FAT Beginning Sector
                ; DX = 0
                cmp ax, word ptr [FAT_BufferSector]
                jne short load_FAT_sectors

                mov cx, word ptr [FAT_CurrentCluster]
                shr cx, 1
                mov ax, word ptr ES:[DI][BX]
                jnc short get_FAT12_nc_even
                shr ax, 1
                shr ax, 1
                shr ax, 1
                shr ax, 1
get_FAT12_nc_even:
                and ah,0Fh
                retn
load_FAT_sectors:
                mov word ptr [FAT_BufferSector], ax
                xor dx, dx
                add ax, word ptr [bp][Hidden1]
                adc dx, word ptr [bp][Hidden2]
                add ax, word ptr [bp][ResSectors]
                adc dx, 0

                mov bx, 7000h
                mov cx, 3
                call proc_read
                jnc short pass_FAT_sectors_load_error
                retn
pass_FAT_sectors_load_error:
                mov ax, word ptr [FAT_CurrentCluster]
                xor dx, dx
                jmp check_next_cluster_fat_type

FAT_CurrentCluster: dw 0
FAT_BufferSector: dw 01A1h

proc_get_next_cluster endp

TRDOS_Kernel:
                db "TRDOS   RTS"
                db 0

proc_find_file  proc near
                xor bx, bx
                mov di, 8000h
                mov cx, word ptr [bp][RootDirEnts]
                push cx
loc_start_scan:
                cmp byte ptr ES:[DI], 0
                je short retn_from_find_file
                push di
                mov cx, 11
                mov si, offset TRDOS_Kernel
loc_next_char:
                cmpsb
                jne next_file_search
                loop loc_next_char
                pop di
                test byte ptr ES:[DI]+0Bh, 10h
                jnz short retn_from_find_file   ; It is a directory (BX=0)

                mov bx, word ptr ES:[DI]+1Ah    ; First Cluster

retn_from_find_file:
                pop cx
                retn

next_file_search:
                pop di
                add di,20h
                pop cx
                push cx
                loop loc_start_scan

                jmp short retn_from_find_file

proc_find_file endp

trio_offset:    dw   0100h
trio_segment:   dw   0800h

trfailedmsg:
		db   0Dh, 0Ah
                db   'DISK IO Error...     '
Register_AX:    db   '0'
		db   '0'
Hex_Sign:       db   'h'
Retry_Msg:      db   0Dh, 0Ah
		db   'Press any key to retry or reboot from another disk...' 

NextLine:       db 0Dh, 0Ah, 0

win_boot_addr:  dw   7C00h
                dw   0
RetryCount:
		db   0A1h

		db   1 dup(1)

Present         ends

                end  start