; *****************************************************************************
;
; INT_21H.ASM  [ TRDOS INT 21h Handler ]
; Copyright (C) 2005 Erdogan TAN  [ 29/01/2005 ]  Last Update: 14/11/2009
;
; TRDOS.ASM (include INT_21H.ASM)
;
; *****************************************************************************

; TRDOS Function Calls

trdos_int21h_routine:
                cmp ah, 9
                jne short pass_int21h_printstr
                push dx
                push ax
                push bx
                mov ah, 0Fh ; Get Video Display Mode
                int 10h
                ;AH= Number of columns
                ;AL= Video mode
                ;BH= Current video page
                mov word ptr CS:[Program_VideoMode],ax 
                mov byte ptr CS:[Program_VideoPage],bh
                pop bx
                push bx
loc_print_$:          
                ; Print String (with $ terminator)
                ; Input -> DS:DX = String Address
                mov     BX, DX
                mov     AL, byte ptr DS:[BX]
                cmp     AL,'$'            
                je      short loc_int21h_9h_return ; AL = $ : end of string
		mov     AH,0Eh                  
                mov     BX, word ptr CS:[Program_CharColorAtr] ;BH= Video Page
		int     10h                     ; BIOS Service func ( ah ) = 0Eh
						; Write char as TTY
						;AL-char BH-page BL-color
                inc     DX
                jmp     short loc_print_$

loc_int21h_1h_getchar:
                ; Output: al, keyboard input with echo
                ; AL= ASCII Code
                ; AH= Scan Code
                push dx
                push ax
                xor ah,ah
                int 16h
                pop dx
                mov dl, al
                mov ax, dx
                push ax
                push bx
                jmp short loc_int21h_1h_echo
loc_int21h_2h_printchar:
                ; Int 21h Function 2h Input: DL, char
                push dx
                push ax
                push bx
loc_int21h_1h_echo:
                mov ah, 0Fh ; Get Video Display Mode
                int 10h
                ;AH= Number of columns
                ;AL= Video mode
                ;BH= Current video page
                mov word ptr CS:[Program_VideoMode],ax 
                mov byte ptr CS:[Program_VideoPage],bh
                mov BL, byte ptr CS:[Program_CharColorAtr]
                mov AL, DL
                mov AH,0Eh
                int 10h                     ; BIOS Service func ( ah ) = 0Eh
                                            ; Write char as TTY
                                            ;AL-char BH-page BL-color
loc_int21h_9h_return:
                pop bx
                pop ax
                pop dx
               ;sti
                iret

loc_get_trdos_version:
                ; INT 21h Function AH= 30h
                ; Return:
                ; AL= Major version number
                ; AH= Minor version number
                ; BX:CX= Build Number
                mov ax, 10 ; TRDOS Version 1.0
                xor bx, bx
                xor cx, cx
                iret
loc_get_return_code:
               ; INT 21h Function AH=4Dh, Get Return Code
               ; temporary
                xor ax,ax
                iret
pass_int21h_printstr:
                ; INT 21h Function: 0 = Terminate Program
                cmp ah, 0
                je run_com_INT20h_handler
                ; INT 21h Function: 1 = Keyboard Input
                cmp ah, 1
                je short loc_int21h_1h_getchar
                ; INT 21h Function: 2 = Display Output
                cmp ah, 2
                je short loc_int21h_2h_printchar
                ; INT 21h Function: 4Ch = Terminate Program
                cmp ah, 4Ch
                je run_com_INT20h_handler
                cmp ah, 4Ah
                je loc_modify_alloc_mem
                cmp ah, 4Bh
                je loc_int21h_function_4Bh
                cmp ah, 35h
                je short loc_get_interrupt_vector
                cmp ah, 25h
                je short loc_set_interrupt_vector
                cmp ah, 2Ch
                je short loc_int21h_get_time
                cmp ah, 2Dh
                je loc_int21h_set_time
                cmp ah, 2Ah
                je loc_int21h_get_date
                cmp ah, 2Bh
                je loc_int21h_set_date
                cmp ah, 30h
                je short loc_get_trdos_version
                cmp ah, 4Dh
                je short loc_get_return_code
                cmp ah, 48h
                je short loc_get_return_code ; Temporary
                cmp ah, 49h
                je short loc_get_return_code ; Temporary
                jmp loc_invalid_function_call
                jmp dword ptr CS:[INT21h_Offset]
loc_get_interrupt_vector:
                ; Get Interrupt Vector
                ; Input -> AL= Interrupt Number
                ; Output -> ES:BX= Interrupt Vector
                xor ah, ah
                mov bx, ax
                shl bx, 1
                shl bx, 1
                xor al, al
                push ds
                mov ds, ax
                mov es, word ptr [BX]+2
                mov bx, word ptr [BX]
                pop ds
                iret
loc_set_interrupt_vector:
                ; Set Interrupt Vector
                ; Input -> AL= Interrupt Number
                ; DS:DX= Interrupt Vector
                xor ah, ah
                push es
                push bx
                mov bx, ax
                shl bx, 1
                shl bx, 1
                xor al, al
                mov es, ax
                mov word ptr ES:[BX], dx
                mov word ptr ES:[BX]+2, ds
                pop bx
                pop es
                iret
loc_int21h_get_time:
                ; INT 21h Function AH= 2Ch
                ; Output:
                ; CH= Hour (0-23)
                ; CL= Minute (0-59)
                ; DH= Second (0-59)
                ; DL= Standard Time = 0
                ; DL= Daylight Savings Time = 1
                mov ah, 02h
                int 1Ah
                mov al, ch
                and al, 0Fh
                mov ah, ch
                shr ah,1
                shr ah,1
                shr ah,1
                shr ah,1
                aad
                mov ch, al
                mov al, cl
                and al, 0Fh
                mov ah, cl
                shr ah,1
                shr ah,1
                shr ah,1
                shr ah,1
                aad
                mov cl, al
                mov al, dh
                and al, 0Fh
                mov ah, dh
                shr ah,1
                shr ah,1
                shr ah,1
                shr ah,1
                aad
                mov dh, al
               ;sti
                iret
loc_int21h_set_time:
                ; INT 21h Function AH= 2Dh
                ; CH= Hour (0-23)
                ; CL= Minute (0-59)
                ; DH= Second (0-59)
                ; DL= Standard Time = 0
                ; DL= Daylight Savings Time = 1
                mov al, ch
                aam
                shl ah, 1
                shl ah, 1
                shl ah, 1
                shl ah, 1
                or ah,al
                mov ch, ah
                mov al, cl
                aam
                shl ah, 1
                shl ah, 1
                shl ah, 1
                shl ah, 1
                or ah,al
                mov cl, ah
                mov al, dh
                aam
                shl ah, 1
                shl ah, 1
                shl ah, 1
                shl ah, 1
                or ah,al
                mov dh, ah
                push cx
                push dx
                mov ah, 02h
                int 1Ah
                mov al, dl
                pop dx
                pop cx
                mov dl, al
                mov ah, 03h
                int 1Ah
                xor ax, ax
                iret
loc_int21h_get_date:
                ; INT 21h Function AH= 2Ah
                ; Output:
                ; CX= Year (1980-2099)
                ; DH= Month (1-12)
                ; DL= Day (1-31)
                mov ah, 04h
                int 1Ah
                mov al, ch
                and al, 0Fh
                mov ah, ch
                shr ah,1
                shr ah,1
                shr ah,1
                shr ah,1
                aad
                mov ch, al
                mov al, cl
                and al, 0Fh
                mov ah, cl
                shr ah,1
                shr ah,1
                shr ah,1
                shr ah,1
                aad
                mov cl, al
                mov al, ch
                mov ah, 100
                mul ah
                xor ch, ch
                add ax, cx
                mov cx, ax
                mov al, dh
                and al, 0Fh
                mov ah, dh
                shr ah,1
                shr ah,1
                shr ah,1
                shr ah,1
                aad
                mov dh, al
                mov al, dl
                and al, 0Fh
                mov ah, dl
                shr ah,1
                shr ah,1
                shr ah,1
                shr ah,1
                aad
                mov dl, al
               ;sti
                iret
loc_int21h_set_date:
                ; INT 21h Function AH= 2Bh
                ; CX= Year (1980-2099)
                ; DH= Month (1-12)
                ; DL= Day (1-31)
                mov ax, cx
                mov cl, 100
                div cl
                mov cl, ah
                mov ch, al
                mov al, cl
                aam
                shl ah, 1
                shl ah, 1
                shl ah, 1
                shl ah, 1
                or ah,al
                mov cl, ah
                mov al, ch
                aam
                shl ah, 1
                shl ah, 1
                shl ah, 1
                shl ah, 1
                or ah,al
                mov ch, ah
                mov al, dh
                aam
                shl ah, 1
                shl ah, 1
                shl ah, 1
                shl ah, 1
                or ah,al
                mov dh, ah
                mov al, dl
                aam
                shl ah, 1
                shl ah, 1
                shl ah, 1
                shl ah, 1
                or ah,al
                mov dl, ah
                mov ah, 05h
                int 1Ah
                xor ax,ax
                iret

loc_modify_alloc_mem:
               ; INT 21h Function AH= 4Ah
               ; Modify Allocated Memory
               ; Input: ES -> Paragraph to be free
               ; BX: New allocation size in paragraphs (with 16 bytes unit)
                xor ax,ax
                iret

loc_int21h_function_4Bh:
               ; 14/11/2009
               ; INT 21h Function AH= 4Bh
               ; Load and Run Executable File
               ; INPUT
               ; AL= Mode (AL=0 Normal execution)
               ; ES:BX= Arguments
               ; DS:DX= Dos Dot File Name Address
                push ax
                push dx
                push cx
                push bx
                push si
                push di
                push ds
                push es
                push bp
                mov word ptr CS:[StackPointer21h], sp
                mov word ptr CS:[StackSegment21h], ss
                inc byte ptr CS:[INT21h_4Bh]
                push cs
                pop  es
                mov si, dx
                ; DS:SI -> ASCIIZ Pathname string beginning address

                ; 14/11/2009
                call proc_check_exe_filename_ext
                jnc short loc_int21h_load_executable_file
                xor ax, ax
                mov byte ptr [INT21h_Err_Code], al
loc_int21h_4Bh_stc_iret:
                dec byte ptr CS:[INT21h_4Bh]
                mov ss, word ptr CS:[StackSegment21h]
                mov sp, word ptr CS:[StackPointer21h]
                pop bp
                pop es
                pop ds
                pop di
                pop si
                pop bx
                pop cx
                pop dx
                pop dx ;ax
                stc
                iret
              
loc_int21h_load_executable_file:
                mov byte ptr CS:[EXE_ID], al
                mov cx, bx ; Char count of the file <= 12
                mov di, offset INT21h_File_name
                push di
                rep movsb
                pop si
                push cs
                pop ds 
                mov ax, 04h
                call proc_open_file
                jnc short loc_INT21h_run_loaded_executable_file
                mov byte ptr [INT21h_Err_Code], ah
                mov al, ah
                xor ah, ah
                jmp short loc_int21h_4Bh_stc_iret

loc_INT21h_run_loaded_executable_file:
                mov word ptr [Run_Segment], ax
                mov word ptr [Run_Offset], 100h
                mov word ptr [PSP_Address], ax
                jmp loc_run_loaded_executable_file_INT21h_4Bh

;End Of INT 21h Function AH=4Bh Load & Run Executable File

loc_invalid_function_call:
                ; Other Functions (invalid)

                pop word ptr CS:[INT_IP]
                pop word ptr CS:[INT_CS]
                pop word ptr CS:[INT_Flags]
                
                push sp
                push bp
                push ss
                push es
                push ds

                push cs
                pop ds

                push di
                push si
                push dx
                push cx
                push bx
                push ax
                call proc_hex
                mov word ptr [ValStr_AX]+2, ax
                pop ax
                mov al, ah
                call proc_hex
                mov word ptr [ValStr_AX], ax

                mov word ptr [ValStr_AH], ax
                mov al, 21h
                call proc_hex
                mov word ptr [ValStr_INT], ax

                mov al, byte ptr [INT_IP]+1
                call proc_hex
                mov word ptr [ValStr_IP], ax
                mov al, byte ptr [INT_IP]
                call proc_hex
                mov word ptr [ValStr_IP]+2, ax

                mov al, byte ptr [INT_CS]+1
                call proc_hex
                mov word ptr [ValStr_CS], ax
                mov al, byte ptr [INT_CS]
                call proc_hex
                mov word ptr [ValStr_CS]+2, ax

                mov al, byte ptr [INT_Flags]+1
                call proc_hex
                mov word ptr [ValStr_Flags], ax
                mov al, byte ptr [INT_Flags]
                call proc_hex
                mov word ptr [ValStr_Flags]+2, ax

                pop bx
                mov al, bh
                call proc_hex
                mov word ptr [ValStr_BX], ax
                mov al, bl
                call proc_hex
                mov word ptr [ValStr_BX]+2, ax

                pop cx
                mov al, ch
                call proc_hex
                mov word ptr [ValStr_CX], ax

                mov al, cl
                call proc_hex
                mov word ptr [ValStr_CX]+2, ax
                
                pop dx
                mov al, dh
                call proc_hex
                mov word ptr [ValStr_DX], ax
                mov al, dl
                call proc_hex
                mov word ptr [ValStr_DX]+2, ax

                pop dx ; si
                mov al, dh
                call proc_hex
                mov word ptr [ValStr_SI], ax
                mov al, dl
                call proc_hex
                mov word ptr [ValStr_SI]+2, ax

                pop dx ; di
                mov al, dh
                call proc_hex
                mov word ptr [ValStr_DI], ax
                mov al, dl
                call proc_hex
                mov word ptr [ValStr_DI]+2, ax

                pop dx ; ds
                mov al, dh
                call proc_hex
                mov word ptr [ValStr_DS], ax
                mov al, dl
                call proc_hex
                mov word ptr [ValStr_DS]+2, ax

                pop dx ; es
                mov al, dh
                call proc_hex
                mov word ptr [ValStr_ES], ax
                mov al, dl
                call proc_hex
                mov word ptr [ValStr_ES]+2, ax

                pop dx ; ss
                mov al, dh
                call proc_hex
                mov word ptr [ValStr_SS], ax
                mov al, dl
                call proc_hex
                mov word ptr [ValStr_SS]+2, ax

                pop dx ; bp
                mov al, dh
                call proc_hex
                mov word ptr [ValStr_BP], ax
                mov al, dl
                call proc_hex
                mov word ptr [ValStr_BP]+2, ax

                pop dx ; sp
                mov al, dh
                call proc_hex
                mov word ptr [ValStr_SP], ax
                mov al, dl
                call proc_hex
                mov word ptr [ValStr_SP]+2, ax

                mov ah, 0
                mov al, 3 ; 80*25 text mode, color with CGA card
                int 10h

                mov si, offset msg_invalid_function_call
                call proc_printmsg
                mov si, offset msg_function_registers
                call proc_printmsg

                jmp run_com_int20h_handler_ctrlbrk


INT21h_File_Name: db 13 dup(0)
INT21h_Err_Code: db 0
INT_IP: dw 0
INT_CS: dw 0
INT_FLAGS: dw 0

msg_invalid_function_call:
                db 7
                db 0Dh, 0Ah, 0Dh, 0Ah
                db "*** Invalid function call for TRDOS ! ***"
                db 0Dh, 0Ah, 0
msg_function_registers:
                db 0Dh, 0Ah
                db "INT "
ValStr_INT:     dw 3030h
                db "h"
                db "    "
                db "Function AH = "
ValStr_AH:      dw 3030h
                db "h"
                db 0Dh, 0Ah, 0Dh,0Ah
                db "Registers: ", 0Dh, 0Ah
                db "AX = "
ValStr_AX:      dd 30303030h
                db "h    "
                db "BX = "
ValStr_BX:      dd 30303030h
                db "h    "
                db "CX = "
ValStr_CX:      dd 30303030h
                db "h    "
                db "DX = "
ValStr_DX:      dd 30303030h
                db "h", 0Dh, 0Ah
                db "CS = "
ValStr_CS:      dd 30303030h
                db "h    "
                db "IP = "
ValStr_IP:      dd 30303030h
                db "h    "
                db "Flags = "
ValStr_Flags:   dd 30303030h
                db "h", 0Dh, 0Ah
                db "DS = "
ValStr_DS:      dd 30303030h
                db "h    "
                db "ES = "
ValStr_ES:      dd 30303030h
                db "h    "
                db "SI = "
ValStr_SI:      dd 30303030h
                db "h    "
                db "DI = "
ValStr_DI:      dd 30303030h
                db "h", 0Dh, 0Ah
                db "SS = "
ValStr_SS:      dd 30303030h
                db "h    "
                db "SP = "
ValStr_SP:      dd 30303030h
                db "h    "
                db "BP = "
ValStr_BP:      dd 30303030h
                db "h", 0Dh, 0Ah, 0Dh, 0Ah, 0

; End Of TRDOS Function Calls
