; CENTRAL.COM (CENTRAL.ASM)
; "Turkish Rational CENTRAL" Standalone Program (TR-CENTRAL v1.0)
; (C)opyright Erdogan Tan - 30 DECEMBER 2000
; Not completed...
; [ Under development since 23/11/2000 ]
; the DEVELOPMENT HISTORY:
; 1993: Starting with AMD 386DX-40, 4 MB RAM, 240 MB fdisk, Sound Blaster Pro
; 1993-1996 : C, Assembly, Visual Basic, DOS, XENIX/UNIX, WINDOWS experiences
; 1996 : Deciding to develop 417 DOS (ALTERNATIVE DOS, TR-DOS), TR-CENTRAL
;        (Planning the final stage as MULTIX 2000 Operation System)
;        (on DEVICE:SECTION:DISPLACEMENT logic)
;        Deciding to use 'TURKISH RATIONAL' mark. Shortly, 'TR'.
; 1996-1998:
;        Visual Basic, C and Assembly Programs
;        ADRES 417, URETIM 417 programs with original DATA INDEXING methods
; 1998:
;        Entrance to Internet, beginning of WEB SITE works
;        (Deciding to use TRANSACTION term instead of EXECUTION or OPERATION)
;        (Revisioning MULTIX-2000 OS plans to MULTIX-2004 TS)
;
; 1998-2000: PRESENTATOR (P2000.ASM), the beginning/rising of TR-DOS.
; 1999:
;        WWW.SINGLIX.COM
;        Deciding to develop SINGLIX before TR-Multix
; 2000:  Finishing of the first TR-DOS Operation System stage (P2000.ASM v1.1)
;        Beginning of TR-CENTRAL Standalone Program development
;        (Beginning of developing/creating TR-MULTIX's particular FS elements)
; 23/11/2000 : Writing CENTRAL's INITIALIZATION code ...
;              (Enabling A20 line, re-vectoring INT 18h)
; 25/11/2000 : Initialization Success !!! (Program will grow by time)
; 28/11/2000 : INT 18h -> AX=01A1h, BH=0 BL=0 Function = Print ASCIIZ string.
;              This function's procedure is placed in Conventional Memory.
;              "If AX <> 01A1h then START TR-CENTRAL (MENUPROG)" func is OK.
; 29/11/2000 : Running INT 18h handler in Extended Memory is OK.
;              (Code located at FFFFh:0300h) (FFFFh:0010h -> 'TR')
; 02/12/2000 : Temporary "Invalid INT 18h Function Call !" function is OK.
; 03/12/2000 : INT 18h -> AX=01A1h, BH=0 BL=1 to FFh
;              Function = Print ASCII ZERO string with requested color in BL.
;              (At current cursor location. On current page.)
;              Return -> BL = 7
;       NOTE : INT 18h -> AX= 01A1h BX=0 is direct write the ASCII ZERO string
;              to Page 0 with Color/Attribute 7. (INT 10h -> AH= 0Eh, BX= 07h)
; 08/12/2000 : INT 18h -> AX= 01A1h BH=1
;              Function = Change color or attribute of a bar (character block)
;              BL= Color&Attrib CL= Number of colums CH= Columns per line
;              DL= Beginning column DL= Beginning line
;              DI= Video buffer segment (ES<-DI, DI<-0) (B800h, B000h etc.)
; 12/12/2000 : INT 18h Entrance code and Function bh0 (bh=0) optimized.
;              ("cmpsw" instruction before "read_port_60h")
; 16/12/2000 : INT 18h AX=01A1h BH=2 BL=0 32 bit single/simple division
;              DX_AX = dividend , CX = divisor
;              DS:SI = pointer for AX, DX, CX
; 16/12/2000 : INT 18h AX=01A1h BH=2 BL>0 32 bit repetitive division
;              BL = number of digits, CX = 10 (divisor), DX_AX = dividend
;              DS:SI = pointer for AX, DX, CX
;              ES:DI = result buffer (for string of decimal result) 
; 17/12/2000 : INT 18h AX=01A1h BH=3 BL = Drive Number
;              Function = Get disk/drive parameters
;              DS:SI = pointer for TR-DOS physical disk parameter table
;              OUTPUT = Parameters recorded in DS:SI fields . CF=1 -> error
; 17/12/2000 : INT 18h AX=01A1h BH=4 BL = the byte to be converted
;              Function = Convert byte to hexadecimal number digits (char)
;              OUTPUT -> AX = Hex number digits in AL (x1) and AH (x16)
; 17/12/2000 : INT 18h AX=01A1h BH=5 BL = Retry Count for failed reading
;              Function = READ DISK SECTORS
;              DS:SI = pointer for TR-DOS physical disk parameter table
;              (OUTPUT : If CF=1 -> reading failed ; CX = remain sectors)
; 24/12/2000 : INT 18h AX=01A1h BH=6 BL= Sector count of the GP Buffer
;              Function = INITIALIZE (RESET) RUN TIME SYSTEM DESCRIPTORS
;              DS:SI = Requested Location of MAIN DESCRIPTOR TABLE
;              ES:DI = Requested Location of General Purpose Buffer
;              OUTPUT => ax = 01A1h -> successful bh = major version of RTS
;              bl = minor version of RTS (TR-CENTRAL)
;              WARNING! All buffers and descriptor data (parameter tables)
;              will be reset. Also, MEMORY ALLOCATION TABLE will be reset...
;        NOTE: Minimum: 7 + total DOS Drives, Maximum: 7+26 sectors must be
;              available (free) from beginning at DS:SI. Otherwise, some
;              data (in these sectors) will be erased/overwritten. Also,
;              offset value for main descriptor table, must be less than
;              65636 - (512*(7+ total DOS drives)) or < BE00h is good...
;  DOS DRIVES: 2 Floppy + 4 Primary + 16 Logical + 4 Virtual = 26 (maximum).
; 28/12/2000 : INT 18h AX=01A1h BH=7 BL= 0 
;              Function = RETURN (GET) MAIN DESCRIPTOR TABLE ADDRESS
;              OUTPUT => ax= offset of MDT, dx= segment of MDT
;              bh= major version of MDT (RTS), bl= minor version of MDT.
;            * BL = 1 -> Function = RETURN MEMORY ALLOCATION TABLE ADDRESS
;              Output => ax= MAT offset, dx= MAT segment, bx= MDT version
;            * BL = 2 -> Function = Return General Purpose Buffer Address
;              Output => ax= GPB offset, dx= GPB segment, bx= sector count
;            * BL = 3 -> Function = RETURN CURRENT DOS DRV PRM. TBL. ADDRESS
;              Output => ax= Offset of Current DOS Drive Parameter Table
;                        dx= Segment of Current DOS Drive Parameter Table
;                        bx= Number of DOS drives (the result of RTS init)
;            * BL = 4 -> Function = RETURN FREE (CONVENTIONAL) MEMORY COUNT
;              Output => ax= First free block number (1 block = 512 bytes)
;                        dx= Free block count from the first block
;                        bx= Total free block count (Free bytes = bx * 512)
;            * BL = 5 -> Function = RETURN FREE CONTINUOUS MEMORY COUNT
;              Output => ax= Beginning block (Beginning of Max. free blocks)
;                        dx= Free continouos block count from the beginning
;                        bx= Total free block count (Free bytes = bx * 512)
;            * BL > 5 -> Invalid Function Call
;###############################################################################
; CENTRAL.ASM (CENTRAL.COM, CENTRAL.BIN)
		PAGE    60,132
Reserved1     equ 12h          ; FFFFh:0012h -> Reserved Word 1
Reserved2     equ 14h          ; FFFFh:0014h -> Reserved Word 2
CentralVer    equ 16h          ; FFFFh:0016h -> TR-CENTRAL Version, 0 -> 1.0
RetryCount    equ 17h          ; Byte ptr, FFFFh:0017h
MDT_Offset    equ 18h          ; Word ptr, FFFFh:0018h
MDT_Segment   equ 1Ah          ; Word ptr, FFFFh:001Ah
GPB_Offset    equ 1Ch
GPB_Segment   equ 1Eh
GPB_Sectors   equ 20h
DOS_Drives    equ 21h
;哪哪哪哪哪 CODE_SEG  哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
CODE_SEG        segment para public
                assume  CS:CODE_SEG, DS:CODE_SEG, SS:CODE_SEG, ES:CODE_SEG
                org     100h                     ; org 7E00h (CENTRAL.BIN)
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;		ENTRY POINT
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;		PROCEDURE proc_start
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
proc_start      proc    near
start:		; N-Ref=0
                jmp     load
                dw  1 dup(01A1h)
proc_start	endp
                org 200h
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;              PROCEDURE proc_handler
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
proc_handler    proc    far
INT18h_handler:
                cld
                cmp ax, 01A1h
                jne short pass_01A1h_function0
                cmp bx, 0
                ja short pass_01A1h_function1
                call proc_print_msg
                IRET
pass_01A1h_function0:
                xor bx, bx
pass_01A1h_function1:
                cli
                push cx
                push di
                push si
                push es
                push ds
                xor si, si
                mov ds, si
                mov di, 0FFFFh
                mov es, di
                mov di, 10h
                cmpsw
                push cs
                pop  ds
                jne short pass_read_port_60h
                call check_input_buffer
                jnz  short return_with_error
                mov  al, 0D0h
                out  64h, al
                call check_input_buffer
                jnz  short return_with_error
                xor cx, cx
read_port_60h:
                in  al, 60h
                and al, 2
                loopz read_port_60h
                jz  short pass_msg_performed
pass_read_port_60h:
                mov di, 10h
                cmp word ptr ES:[DI], 'RT'
                je short pass_msg_tr_failed
                mov  si, offset msg_tr_failed
                call proc_print_msg
                mov  si, offset msg_01A1h
                call proc_print_msg
                jmp short return_from_INT18h
pass_msg_tr_failed:
                call dword ptr [Extended_Int18h_Handler]
                jmp short return_from_INT18h
pass_msg_performed:
                call proc_enable_a20_line
                jnz  short return_with_error
                mov si, offset msg_A20_line_enabled
                call proc_print_msg
                jmp short pass_msg_tr_failed
check_input_buffer:
                xor cx, cx
loc_in_al:
                in al, 64h
                and al, 2
                loopnz loc_in_al
                retn
return_with_error:
                mov  si, offset msg_tr_failed
                call proc_print_msg
                mov  si, offset msg_a20_line
                call proc_print_msg
return_from_INT18h:
                pop ds
                pop es
                pop si
                pop di
                pop cx
                sti
                IRET
proc_handler    endp
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;              PROCEDURE proc_enable_a20_line
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
proc_enable_a20_line  proc near
enable_a20_line:
                mov  al, 0D1h
                out  64h, al
                call check_input_buffer
                jnz  short return_from_enabling
                mov al, 0DFh
                out 60h, al
                call check_input_buffer
return_from_enabling:
                retn
proc_enable_a20_line endp
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;              PROCEDURE proc_print_msg
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
proc_print_msg  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_print_msg  endp
msg_tr_failed:
                db 07h
                db 0Dh, 0Ah
                db 'TRANSACTION FAILED !'
                db 0Dh, 0Ah
                db 'Error Code : '
                db 0
msg_a20_line:
                db 'A20'
                db 0Dh, 0Ah, 0
msg_01A1h:
                db '01A1h'
                db 0Dh, 0Ah, 0
msg_A20_line_enabled:
                db 07h
                db 0Ah, 0Dh
                db 'A20 LINE ENABLED ...'
                db 0Ah, 0Dh, 0
var_INT18h_off: dw 0
var_INT18h_seg: dw 0
Extended_Int18h_Handler:
                dw 0300h  ; Offset
                dw 0FFFFh ; Segment
ReservedWord:
                dw 0A500h
                org 300h
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;              PROCEDURE proc_ext_int18h
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
proc_ext_int18h proc    far
begin:
                pop word ptr CS:[Reserved1]
                pop word ptr CS:[Reserved2]
                pop ds
                pop es
                pop si
                pop di
                pop cx
                push cx
                push di
                push si
                push es
                push ds
                push word ptr CS:[Reserved2]
                push word ptr CS:[Reserved1]
                cmp bx,0
                ja short pass_start_menuprog
start_menuprog:
                mov si, offset msg_performed
                call call_from_start_menuprog
                retf
pass_start_menuprog:
                mov al,bh
                cbw
                shl ax, 1
                push bp
                mov bp, ax
                add bp, 100h
                call word ptr CS:[BP]
                pop bp
                retf
function_bh0:
              ; push bx
                mov ah, 0Fh
                int 10h
              ; pop ax
              ; mov bl, al
                push bx
                mov ah, 3
                int 10h
                push ds
                push si
                pop bp
                pop es
                xor cx, cx
loc_scanb:
                lodsb
                and al,al
                jz short pass_repeat_scanb
                inc cx
                jmp short loc_scanb
pass_repeat_scanb:
                mov ax, 1301h
                int 10h
retn_from_bh0:
                pop bx
                mov bl, 7
                mov ax, 0920h
                mov cx, 80
                int 10h
                retn
function_bh1:
                push di
                push cx
                push di
                pop  es
                mov al, dh
                mul ch
                add al, dl
                adc ah, 0
                shl ax, 1
                mov di, ax
                xor ch, ch
change_next_column_color:
                mov byte ptr ES:[DI]+1, bl
                inc di
                inc di
                loop change_next_column_color
                pop cx
                pop di
                retn
function_bh2:
                ; DI:SI = Pointer for AX, DX, CX, BX from caller
                mov ax, word ptr [SI]
                mov bx, word ptr [SI]+2
                mov cx, word ptr [SI]+4
                and bl, bl
                jz short rxdos_div32
                xor bh, bh
                mov cx, 10 ; Divisor
trdos_re_div32:
                push bp
                mov  bp, bx                   ; Repetition, number of digits
rediv32_divide_loop:
                call rxdos_div32
                add bl, '0'                   ; To make visible
                mov byte ptr ES:[DI][bp], bl  ; ES:DI = Result Buffer 
                dec bp
                or ax, ax
                ja short rediv32_divide_loop
                or dx, dx
                ja short rediv32_divide_loop
fill_digit_space:
                mov byte ptr ES:[DI][bp], 20h
                or bp, bp
                jna short end_of_rediv32
                dec bp
                jmp short fill_digit_space
end_of_rediv32:
                pop bp
                retn
rxdos_div32:
              ; DX_AX = 32 bit dividend
              ; CX = 16 bit divisor
                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
             ; DX_AX = 32 bit quotient
             ; BX = 16 bit remainder
             ; CX = 16 bit divisor
                retn
function_bh3:
               push dx
               mov byte ptr [SI], bl    ; Drive number
               mov dl, bl
               mov ah, 8
               int 13h
               jnc short dparam_no_error
               call proc_hex
               ; AX = Error code , DS:SI = Disk parameter table (offset +2)
               stc
               jmp short return_from_dparam
dparam_no_error:
               mov byte ptr [SI]+1, dl  ; Number of (this type) disks
               mov word ptr [SI]+2, 200h ; Bytes per Sector
               push cx
               and cl, 3Fh
               xor ch, ch
               ; DS:SI = disk parameter table (offset +2)
               mov word ptr [SI]+4, cx  ; Sector per Track
               pop cx
               mov dl, dh
               xor dh, dh
               inc dx
               mov word ptr [SI]+6, dx  ; Heads
               shr cl, 1
               shr cl, 1
               shr cl, 1
               shr cl, 1
               shr cl, 1
               shr cl, 1
               xchg ch, cl
               inc cx
               mov word ptr [SI]+8, cx  ; Cylinders
             ; ES:DI = BIOS disk parameter table address (INT 13h output)
               mov word ptr [SI]+22, di
               mov word ptr [SI]+24, es
             ; DS:[SI]+12 = Current disk sector (linear)
             ; DS:[SI]+16 = Sector count 
             ; DS:[SI]+18 = Buffer offset
             ; DS:[SI]+20 = Buffer segment
             ; DS:[SI]+22 = BIOS disk parameter table offset
             ; DS:[SI]+24 = BIOS disk parameter table segment
             ; DS:[SI]+26 = Number of sectors, low word
             ; DS:[SI]+28 = Number of sectors, hight word
             ; DS:[SI]+30 = Reserved word
               cmp byte ptr [SI], 80h
               jb  short dparam_15h_error
               mov dl, byte ptr [SI]           ; Drive number
               mov ah, 15h
               int 13h
               jc  short dparam_15h_error
               mov word ptr [SI]+26, dx
               mov word ptr [SI]+28, cx
               mov al, 15h
               mov word ptr [SI]+30, ax
               xor ax, ax
return_from_dparam:
               mov word ptr [SI]+10, ax
               pop dx
               retn
dparam_15h_error:
               xor ax, ax
               mov word ptr [SI]+26, ax
               mov word ptr [SI]+28, ax
               mov word ptr [SI]+30, ax  ; Reset of the reserved word
               jmp short return_from_dparam
function_bh4:
               mov al, bl
proc_hex:      
               db 0D4h, 10h             ; AAM 
                                        ; output : AH = AL / 10h
                                        ;          AL = AL mod 10h
               or ax, '00'
               xchg ah, al
               cmp al, '9'
               jna short pass_cc_al
               add al, 7
pass_cc_al:
               cmp ah, '9'
               jna short retn_from_bh4
               add ah, 7
retn_from_bh4:
               retn
function_bh5:
               ; BL = Retry count
               ; Number of sectors is in DS:[SI]+16,
               ; beginning sector is in DS:[SI]+12,
               ; buffer is in DS:[SI]+18,
               ; drive number is in DS:[SI]
               ; sector per track is in DS:[SI]+4
               ; heads is in DS:[SI]+6
               ; bytes per sector is in DS:[SI]+2
               ; error code will be in DS:[SI]+10
               mov byte ptr CS:[RetryCount], bl
               mov cx, word ptr [SI]+16
               mov ax, word ptr [SI]+12
               mov dx, word ptr [SI]+14
               mov es, word ptr [SI]+20
               mov bx, word ptr [SI]+18
               mov word ptr [SI]+10, 3030h     ; Error code
proc_read:
               push    CX                      ; Number of sectors
               push    AX                      
               push    DX                      ; DX_AX = beginning sector
               mov     CX,Word Ptr [SI]+4      ; Sectors per track
               push    BX
               call    rxdos_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 [SI]+6     ; Number of Heads
                call    rxdos_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 [SI]       ; Drive number
		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_read_error   ; error code in AH
               xchg    AH,AL                   ; now it is in AL
               call    proc_hex                ; Makes error code to visible
               mov     Word Ptr [SI]+10,AX     
               stc                             ; Set carry flag, again
pass_read_error:
               pop     DX                      ; DX_AX = Current Sector
               pop     AX
               pop     CX                      ; CX = Sector count
               jc      short dec_retry_count
               add     AX,1
               adc     DX,0    
               jc      short retn_from_bh5                 
               add     BX,Word Ptr [SI]+2    ; Bytes per sector
               jnc     short pass_next_buffer_segment
               push    BX
               mov     BX, ES  
               add     BX, 1000h
               mov     ES, BX
               clc   ; Return from F000 to 0 will be accepted.
               pop     BX
pass_next_buffer_segment:
               loop    proc_read            ; Repeat if CX > 0
               retn
dec_retry_count:
               dec     Byte Ptr CS:[RetryCount]
               jnz     short proc_read
retn_from_bh5:
               retn
function_bh6:
               push ds
               xor ax, ax                  ; Instead of
               dec ax                      ; MOV AX, 0FFFFh instruction
               mov ds, ax
               pop ax
               mov word ptr DS:[MDT_Offset], si
               mov word ptr DS:[MDT_Segment], ax  ; DS
               mov word ptr DS:[GPB_Offset], di
               mov word ptr DS:[GPB_Segment], es
               mov byte ptr DS:[GPB_Sectors], bl
               mov byte ptr DS:[DOS_Drives], 0
               mov ds, ax
               mov word ptr [SI], 'DM'      ; MDT Sign And Version (0)
               mov byte ptr [SI]+2, 'T'
               mov byte ptr [SI]+3, 0
               mov word ptr [SI]+4, DI      ; General Purpose Buffer Offset
               mov word ptr [SI]+6, ES      ; General Purpose Buffer Segment
               xor bh, bh
               mov word ptr [SI]+8, BX      ; GP Buffer Sector Count
               mov bx, si
               add bx, 128
               mov word ptr [SI]+116, BX    ; Offset of V. Disk Parameter Tbl.
               mov word ptr [SI]+118, DS    ; Segment of Virtual Disk P. Tbl.
               mov word ptr [SI]+120, 0420h ; [SI]+120= Number of vdisks, 4
                                            ; [SI]+121= Table size, 32 bytes
                                            ; [SI]+128 -> Virtual Disk P. Tbl.
                                            ; !!! Virtual disk functions not
                                            ; included by this RTS version !!!
               add bx, 128
               mov word ptr [SI]+16, BX     ; Offset of P. Disk Parameter Tbl.
               mov word ptr [SI]+18, DS     ; Segment of Physical Disk P. Tbl.
               mov word ptr [SI]+20, 0820h  ; [SI]+20= Number of Disks, 8
                                            ; [SI]+21= Table size, 32 bytes
                                            ; [SI]+256 -> P. Disk Paramater T.
               add bx, 256
               mov word ptr [SI]+10, BX     ; Offset of Memory Alloc Table
               mov word ptr [SI]+12, DS     ; Segment of Memory Alloc Table
               mov word ptr [SI]+14, 2048   ; Size of MAT in bytes
               add bx, 2048
               mov word ptr [SI]+22, BX     ; Offset of P. DOS Partition Tbl.
               mov word ptr [SI]+24, DS     ; Segment of Primary DOS P. Tables
               mov word ptr [SI]+26, 0404h  ; [SI]+26= Number of P. DOS P.
                                            ; [SI]+27= Number of Ext. DOS P.
                                            ; [SI]+21= Table size, 32 bytes
                                            ; [SI]+2048+256 = non-dos partition
                                            ; tables. 8 tables, 32 bytes/table
               add bx, 512
               mov word ptr [SI]+28, BX     ; Offset of Logical DOS P. Tables
               mov word ptr [SI]+30, DS     ; Segment of L. DOS Partition Tbl.
               mov word ptr [SI]+32, 1020h  ; [SI]+32= Number of L. DOS P.
                                            ; [SI]+33= Table size, 32 bytes
               add bx, 512
               mov word ptr [SI]+34, BX     ; Offset of Current DOS Drv Tbl.
               mov word ptr [SI]+36, DS     ; Segment of Current DOS Drv Tbl.
               mov word ptr [SI]+38, 0      ; [SI]+38= DOS Drive Number
                                            ; [SI]+39= File System Type
                                            ; 0= Non-dos or unknown
                                            ; 1= FAT 12 ;12 bit cluster
                                            ; 2= FAT 16 ;16 bit cluster
                                            ; 3= FAT 32 ;28 (+4) bit cluster
                                            ; 4= FAT 24 ;24 (+8) bit cluster
                                            ; FAT 24 is a TR-DOS FS Feature
               add bx, 512
               mov word ptr [SI]+40, BX     ; Offset of DOS Drive Tables
               mov word ptr [SI]+42, DS     ; Segment of DOS Drive Tables
               mov word ptr [SI]+44, 0      ; [SI]+44= Number of DOS Drives
                                            ; [SI]+45= Drive Table Version (0)
           ;   mov word ptr [SI]+46, 0      ; Location of Source (Read) Buffer
           ;   mov word ptr [SI]+48, 0
           ;   mov word ptr [SI]+50, 0      ; Source Device (Read) Buffer size
           ;   mov word ptr [SI]+52, 0      ; Source device
                                            ; [SI]+52 -> Disk or dos drive no.
                                            ; [SI]+53 -> 0 = non-dos (disk)
                                            ; [SI]+53 -> 1-4 = FAT (DOS drive)
           ;   mov word ptr [SI]+54, 0      ; Location of Dest (Write) Buffer
           ;   mov word ptr [SI]+56, 0
           ;   mov word ptr [SI]+58, 0      ; Destination Device Buffer size
           ;   mov word ptr [SI]+60, 0      ; Destination device
                                            ; [SI]+60 -> Disk or dos drive no.
                                            ; [SI]+61 -> 0 = non-dos (disk)
                                            ; [SI]+61 -> 1-4 = FAT (DOS drive)
           ;   mov dword ptr [SI]+64, 0     ; Location of FAT Description Tbl.
           ;   mov dword ptr [SI]+68, 0     ; Location of FAT Buffer
           ;   mov word ptr [SI]+72, 0      ; FAT Buffer Size in sectors
           ;   mov dword ptr [SI]+74, 0     ; Location of DIR Description Tbl.
           ;   mov dword ptr [SI]+78, 0     ; Location of DIRECTORY Buffer
           ;   mov word ptr [SI]+82, 0      ; DIR Buffer Size in sectors
           ;   mov dword ptr [SI]+84, 0     ; Source File Description Table
           ;   mov dword ptr [SI]+88, 0     ; Source File Cluster Chain
           ;   mov word ptr [SI]+92, 0      ; Number of Source File Clusters
           ;   mov dword ptr [SI]+94, 0     ; Destination File Desc. Table
           ;   mov dword ptr [SI]+98, 0     ; Destination File Cluster Chain
           ;   mov word ptr [SI]+102, 0     ; Number of Dest File Clusters
           ;   mov dword ptr [SI]+104, 0    ; Current Dir Cluster Chain
           ;   mov word ptr [SI]+108, 0     ; Number of Current Dir Clusters
           ;   mov word ptr [SI]+110, 0     ; Free Memory Sectors
           ;   mov word ptr [SI]+112, 0     ; Max. free continuous mem secs
           ;   mov word ptr [SI]+114, 0     ; Beginning of max. free  sectors
           ;   mov byte ptr [SI]+122, 0     ; Number of open files
           ;   mov byte ptr [SI]+123, 0     ; Maximum number of open files
           ;   mov word ptr [SI]+124, 0     ; Reserved
           ;   mov word ptr [SI]+126, 0     ; Reserved
               mov di, si
               add di, 46
               push ds
               pop es
               xor ax, ax
               mov cx, 1513                 ; 233 + 2048/2 + 512/2
               rep stosw
               mov word ptr [SI]+62, '01'   ; RTS Version (1.0)
; ############ Memory Allocation Table initialization #######################
               push ds
               xor ax, ax                  ; Instead of
               dec ax                      ; MOV AX, 0FFFFh instruction
               mov ds, ax
               add si, 512               ; Memory Allocation Table Offset
               mov di, si
               mov ax, 0101h             ; 1 = Reserved area identifier
               mov cx, 4                 ; 8 blocks
               rep stosw                 ; Memory location = 0-4096 (0-1000h)
               mov dx, word ptr DS:[GPB_Segment]
               mov ax, word ptr DS:[GPB_Offset]
               call Convert_Address_to_Memory_Block
               mov di, si
               add di, ax                ; MAT Block Offset
               xor ch, ch
               mov cl, byte ptr DS:[GPB_Sectors]
               mov al, 2                 ; 2 = General purpose buffer
               rep stosb
               mov di, si                ; MAT Offset
               mov dx, word ptr DS:[MDT_Segment]
               mov ax, word ptr DS:[MDT_Offset]
               call Convert_Address_to_Memory_Block
               add di, ax                ; MAT Block Offset
               mov al, 3                 ; 3 = Main Descriptor Table
               stosb
               mov ax, 0404h             ; 4 = Memory Allocation Table
               stosw
               stosw
               mov al, 5                 ; 5 = Partition parameter tables
               stosb
               mov al, 6                 ; 6 = Current DOS drv parameter tbl.
               stosb
               xor ch, ch
               mov cl, byte ptr DS:[DOS_Drives]
               mov al, 7                 ; 7 = DOS drive parameter tables
               rep stosb
               mov al, 8                 ; 8 = Boot Sector Buffer
               mov byte ptr ES:[SI]+62, al  ; SI = MAT offset,
                                         ; 62 = Mem. block no. of 0:7C00h 
                                         ; 512+62 = 574 = memory block offset
               mov di, si
               add di, 1280
               mov ax, 0101h             ; 1 for A000:0000 to FFFF:000F 
               mov cx, 384
               rep stosw
                                         ; 9 = TR-DOS kernel
                                         ; 0Ah = FAT Buffer Description Table
                                         ; 0Bh = FAT Buffer
                                         ; 0Ch = DIR Buffer Description Table
                                         ; 0Dh = DIRECTORY Buffer
                                         ; 0Eh = Transaction Descriptor Table
                                         ; 0Fh = Undefined DATA (buffer etc.)
                                         ; 10h-EFh = Files (14 open files)
                                         ; ?0h -> File Description Table
                                         ; ?1h -> 1'st part of file
                                         ; ?Eh -> 14'th part of file
                                         ; ?Fh -> undefined data for file
                                         ; F0h-FFh = Reserved for TR-DOS
               pop ds
; ############ Disk Parameters Tables initialization ########################
               xor bl, bl
               sub si, 256               ; DS:SI = MAT location
                                         ; SI-256 = Offset of fd0 Param. Tbl.
               push si
               call function_bh3
               cmp byte ptr [SI]+1, 2
               jb short pass_dpt_init_fd
               mov bl, 1
               add si, 32                ; SI+32 = Offset of fd1 Param. Tbl.
               call function_bh3
pass_dpt_init_fd:
               pop si
               add si, 64
               mov bl, 80h
               call function_bh3
               xor ch, ch
               mov cl, byte ptr [SI]+1
repeat_dpt_init_hd:
               cmp cl, 2
               jb short end_of_dpt_init_hd
               dec cl
               inc bl
               push cx
               add si, 32
               call function_bh3
               pop cx
               loop repeat_dpt_init_hd
end_of_dpt_init_hd:
           ;  PROCEDURE initialize DOS drives (A: -> Z:)
           ;  the CODE is NOT READY yet
           ;  (Partition description tables and
           ;  dos drive description tables would be initialized, here)
           ;  End of DOS drive initialization procedure
               push ds
               xor ax, ax                  ; Instead of
               dec ax                      ; MOV AX, 0FFFFh instruction
               mov ds, ax
               xor dh, dh
               mov dl, byte ptr DS:[DOS_Drives]  ; Number of DOS drives
               mov bh, 0                   ; Version 1.0
               mov bl, byte ptr DS:[GPB_Sectors]
               pop ds
               mov ax, 01A1h               ; Successful
            ; NOTE: DS:SI and ES:DI will be returned with their
            ; beginning values, already, they are MDT and GPB pointers
            ; ALSO, Version number recorded at DS:[SI]+62 (MDT offset 62)
               retn
Convert_Address_to_Memory_Block:
               ; dx = Segment
               ; ax = Offset
               push ax
               mov ax, 16
               mul dx
               pop cx
               add ax, cx
               adc dx, 0
               add ax, 511
               adc dx, 0
               mov cx, 512
               call RXDOS_DIV32
               ; AX = Block Number
               ; DX = 0
               ; CX = 512
               ; BX = Remainder of DX_AX + 511
end_of_catmb:
               retn
function_bh7:
              cmp bl, 5
              ja invalid_fcall
              cmp bl, 2
              jz short loc_bh7_bl2
              mov si, word ptr CS:[MDT_Offset]
              mov ds, word ptr CS:[MDT_Segment]
              ja short loc_bh7_bl3
              and bl, bl
              mov bx, word ptr [SI]+62 ; Version
              jz short loc_bh7_bl0
              add si, 512              ; MAT offset
loc_bh7_bl0:
              mov ax, si
              mov dx, ds
              retn 
loc_bh7_bl2:
              mov ax, word ptr CS:[GPB_Offset]
              mov dx, word ptr CS:[GPB_Segment]
              xor bh, bh
              mov bl, byte ptr CS:[GPB_Sectors]
              retn
loc_bh7_bl3:
              cmp bl, 3
              jnz short loc_bh7_bl4_bl5
              mov ax, word ptr [SI]+34   ; Offset
              mov dx, word ptr [SI]+36   ; Segment
              mov bh, byte ptr [SI]+38   ; DOS drive number (0 based)
              mov bl, byte ptr CS:[DOS_Drives] ; Number of DOS drives
              retn
loc_bh7_bl4_bl5:
              mov cx, 2048
              add si, 511
              mov di, si
              xor ax, ax
repeat_bh7_scan_mat0:
              inc si
              cmp byte ptr [SI], 0
              ja short pass_inc_bh7_scan_mat0
              inc ax
pass_inc_bh7_scan_mat0:
              loop repeat_bh7_scan_mat0
              mov cx, 2048
              mov si, di
              xor dx, dx
              cmp bl, 4
              mov bx, ax                     ; Total free blocks (512 bytes)
              ja short repeat_bh7_scan_mat2
repeat_bh7_scan_mat1:
              inc si
              cmp byte ptr [SI], 0
              je short pass_inc_bh7_scan_mat1
              loop repeat_bh7_scan_mat1
              mov ax, 0FFFFh
              retn
pass_inc_bh7_scan_mat1:
              mov ax, si
              inc di
              sub ax, di
              inc dl
              jmp short bh7_scan_mat1x_dec_cx
repeat_bh7_scan_mat1x:
              inc si
              cmp byte ptr [SI], 0
              ja short pass_inc_bh7_scan_mat1x
              inc dx
bh7_scan_mat1x_dec_cx:
              loop repeat_bh7_scan_mat1x
pass_inc_bh7_scan_mat1x:
              retn
repeat_bh7_scan_mat2:
              inc si
              cmp byte ptr [SI], 0
              je short pass_inc_bh7_scan_mat2
              loop repeat_bh7_scan_mat2
              mov ax, 0FFFFh
              retn
pass_inc_bh7_scan_mat2:
              inc dl
              mov bp, si
              inc di
              sub bp, di
              xor ax, ax
              inc al
              jmp short bh7_scan_mat2x_dec_cx
repeat_bh7_scan_mat2x:
              inc si
              cmp byte ptr [SI], 0
              ja short pass_inc_bh7_scan_mat2x
              inc ax
bh7_scan_mat2x_dec_cx:
              loop repeat_bh7_scan_mat2x
              inc si
              and ax, ax
              jnz short pass_inc_bh7_scan_mat2x
              mov ax, bp
              retn
pass_inc_bh7_scan_mat2x:
              cmp ax, dx
              jb short pass_bh7_chg_mb_count_base
              mov dx, ax
              mov bp, si
              add ax, di
              sub bp, ax
pass_bh7_chg_mb_count_base:
              xor ax, ax
              and cx, cx
              jnz short bh7_scan_mat2x_dec_cx
              mov ax, bp
              retn
invalid_fcall:
                mov si, offset msg_invalid
call_from_start_menuprog:
                push cs
                pop ds
                mov bl, 7
                call function_bh0
                stc
                retn
msg_Performed:
                db      07h
                db      0Ah, 0Dh
                db      'Extended INT 18h Function Call Performed ...'
                db      0Ah, 0Dh, 0h
msg_Invalid:
                db      07h
                db      0Ah, 0Dh
                db      'Invalid INT 18h Function Call !'
                db      0Ah, 0Dh, 0h
                db '417'
proc_ext_int18h endp
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;              PROCEDURE proc_load
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
proc_load       proc    near
load:          
                xor     BX,BX
                mov     ES,BX
                mov     BX,60h
                cmp     Word ptr ES:[BX], 200h
                jnz     short pass_INT18h_segment_ctrl
                cmp     Word ptr ES:[BX]+2, 0
                jnz     short pass_INT18h_segment_ctrl
                mov     AX, word ptr ES:[var_INT18h_off]
                mov     DX, word ptr ES:[var_INT18h_seg]
                jmp     short pass_change_vectors
pass_INT18h_segment_ctrl:
                mov     AX, word ptr ES:[BX]
                mov     DX, word ptr ES:[BX]+2
                mov     word ptr ES:[BX], 200h
                mov     word ptr ES:[BX]+2, 0
pass_change_vectors:
                mov     Word Ptr [var_INT18h_off],AX
                mov     Word Ptr [var_INT18h_seg],DX
                mov     si, offset INT18h_handler
                mov     di, 200h
                mov     cx, 80h
                rep     movsw
              ; mov     ax, 3
              ; int     10h
                mov     SI, offset msg_central_start
                call    proc_print_msg
                call    proc_enable_a20_line
                jnz     short A20_line_error
                mov di, 0FFFFh
                mov es, di
                mov di, 10h
                mov word ptr ES:[DI], 'RT'
                mov word ptr ES:[CentralVer], 0400h
                                            ; 0 = Central Version 1.0
                                            ; 4 = Init Value of Retry Count
                mov di, 300h
                mov si, offset Begin
                mov cx, offset Load
                sub cx, si
                rep movsb
                mov di, 100h
                mov ax, offset function_bh0
                stosw
                mov ax, offset function_bh1
                stosw
                mov ax, offset function_bh2
                stosw
                mov ax, offset function_bh3
                stosw
                mov ax, offset function_bh4
                stosw
                mov ax, offset function_bh5
                stosw
                mov ax, offset function_bh6
                stosw
                mov ax, offset function_bh7
                stosw
                mov cx, 2FEh
                sub cx, di
                shr cx, 1
                mov ax, offset invalid_fcall
                rep stosw
                xor dx, dx
                mov es, dx       ; GP Buffer Segment
                mov si, 3800h    ; MDT Offset
                mov di, 1000h    ; GP Buffer Offset
                push ds
                mov ds, dx       ; MDT Buffer Segment
                mov bl, 20       ; GP Buffer Size
                call function_bh6
                pop ds
                cmp ax, 01A1h
                jnz short Initialization_Error
loc_exit:
                int     20h
A20_line_error:
                mov si, offset A20_line_error
                call proc_print_msg
                int     20h
Initialization_Error:
                mov si, offset Msg_Init_error
                call proc_print_msg
                int     20h
msg_central_start:
                db      07h
                db      0Ah, 0Dh
                db      'STARTING TR-CENTRAL ...'
                db      0Ah, 0Dh, 0h
msg_a20_line_error:
                db      07h
                db      0Ah, 0Dh
                db      'A20 LINE ERROR !'
                db      0Ah, 0Dh, 0h
Msg_init_error:
                db      07h
                db      0Ah, 0Dh
                db      'INITIALIZATION FAILED !'
                db      0Ah, 0Dh, 0h
Msg_tr_error:
                db      07h
                db      0Ah, 0Dh
                db      'TRANSACTION FAILED !'
                db      0Ah, 0Dh
                db      'Error Code: '
Error_Code:     dw      3030h
                db      'h'
                db      0Dh, 0Ah, 0h
proc_load       endp
CODE_SEG        ends
		end	start