Metropoli BBS
VIEWER: newxdir.asm MODE: TEXT (ASCII)
;XDIR.COM for the IBM Personal Computer - 1986 by Jeff Prosise
code          segment para public 'code'
              assume cs:code
              org 100h
begin:        jmp initialize                ;goto initialization code
;
copyright          db 'Copyright 1986 Ziff-Davis Publishing Co.',1Ah
global             db '\*.*',0              ;global directory filespec
dos_segment        dw ?                     ;DOS segment
busy_flag          dw ?                     ;offset of DOS BUSY_FLAG
program_status     db 0                     ;XDIR processing status
flag_13h           db 0                     ;status of interrupt 13h
request_flag       db 0                     ;status of processing request
adapter            db 2                     ;0 = MDA, 1 = CGA, 2 = EGA
video_segment      dw 0B800h                ;video segment address
video_page         db ?                     ;current video page
border_attr        db 4Fh                   ;window border attribute
text_attr          db 0Fh                   ;window text attribute
video_address      dw ?                     ;window start address
cursor_mode        dw ?                     ;cursor shape
cursor_pos         dw ?                     ;cursor position
maxlen             db ?                     ;maximum input string length
max_page           db ?                     ;number of highest directory page
dir_page           db ?                     ;current directory page
end_flag           db ?                     ;status of text write routines
error_flag         db ?                     ;critical error status
default_cursor     dw 0607h                 ;default cursor shape (color)
addr_6845          dw ?                     ;CRT Controller base address
search_attr        dw 0                     ;file search attribute
;
path               dw 0                          ;pointer to pathname buffer
dta                dw 64                         ;pointer to Disk Transfer Area
screen_buffer      dw offset initialize          ;pointer to screen buffer
text_buffer        dw offset initialize+1536     ;pointer to filename buffer
;
keyboard_int       label dword              ;old interrupt 9 vector
old9h              dw 2 dup (?)
timer_int          label dword              ;old interrupt 1Ch vector
old1ch             dw 2 dup (?)
bdisk_int          label dword              ;old interrupt 13h vector
old13h             dw 2 dup (?)
bp_int             label dword              ;old interrupt 28h vector
old28h             dw 2 dup (?)
;
old_dta_segment    dw ?                     ;old DTA segment address
old_dta_offset     dw ?                     ;old DTA offset address
old24h_segment     dw ?                     ;old interrupt 24h routine segment
old24h_offset      dw ?                     ;old interrupt 24h routine offset
enable_values      db 2Ch,28h,2Dh,29h       ;values to enable CGA output
                   db 2Ah,2Eh,1Eh
errtext            db 'No Files Found',0
;
;------------------------------------------------------------------------------
;Execution comes here thru interrupt 9 every time a key is pressed or released.
;------------------------------------------------------------------------------
keyboard      proc near
              sti                           ;set interrupt enable flag
              push ax                       ;save AX
              in al,60h                     ;get scan code from keyboard
              cmp al,52                     ;was the '.' key pressed?
              jne kb2                       ;no, then exit to normal handler
              mov ah,2                      ;check shift key status
              int 16h
              test al,8                     ;is the Alt key pressed?
              je kb2                        ;no, then exit
              call kb_reset                 ;reset keyboard, issue EOI
              pop ax                        ;restore AX
              cmp program_status,0          ;XDIR routine already active?
              jne kb1                       ;yes, then don't set request flag
              mov request_flag,1            ;set request flag
kb1:          iret                          ;end interrupt routine
kb2:          pop ax                        ;restore AX
              jmp keyboard_int              ;goto original keyboard routine
keyboard      endp
;
;------------------------------------------------------------------------------
;Interrupt 1Ch handling routine.
;This procedure will now be used to handle int 8 instead of int 1c
;------------------------------------------------------------------------------
timer         proc near
              pushf                         ;call original routine
              call timer_int
              cmp request_flag,0            ;request flag set?
              je timer1                     ;no, then exit
              push es                       ;save ES and DI
              push di
              mov es,dos_segment            ;get DOS segment in ES
              mov di,busy_flag              ;address of DOS BUSY_FLAG in DI
              cmp byte ptr es:[di],0        ;DOS service currently active?
              pop di                        ;clean up the stack
              pop es
              jne timer1                    ;yes, then we must wait
              cmp flag_13h,0                ;BIOS disk service active?
              jne timer1                    ;yes, then don't interrupt it

test_8259_status:
              push   AX                  ;Save altered registers
              push   DX
              mov    DX,20h              ;Port address of 8259 OCW3
              mov    AL,03               ;Set the In-Service Reg. read
                                         ;bits RR=1 and RIS=1
              out    DX,AL               ;Tell 8259 to send ISR on next read
              jmp    short get_mask      ;This causes a 7 clock delay period
                                         ;on the AT to allow time for the 8259
                                         ;to setup the ISR status for us     
get_mask:
              in     AL,DX               ;Get the ISR
              or     AL,AL               ;Set zero flag if no interrupts are
                                         ;being serviced
              pop    DX                  ;Restore the altered registers
              pop    AX

              jnz  timer1                ;A hard interrupt is in progress
              mov request_flag,0            ;reset request flag
              call directory                ;invoke directory routine
timer1:       iret                          ;done - exit
timer         endp
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------



;------------------------------------------------------------------------------
;Interrupt 13h handling routine.
;------------------------------------------------------------------------------
bdisk         proc far
              inc flag_13h         ;Set the busy flag
              pushf                ;Simulate an interrupt call to the 
              call bdisk_int       ;original disk interrupt routine
              pushf                ;Save returned flags from disk interrupt
              dec flag_13h         ;Clear the busy flag
              popf                 ;Restore disk I/O status flags
              ret 2                ;Far return and discard flags on the stack
bdisk         endp
;
;------------------------------------------------------------------------------
;Interrupt 28h handling routine.
;------------------------------------------------------------------------------
backproc      proc near
              pushf                         ;call original routine
              call bp_int
              cmp request_flag,0            ;request flag clear?
              je bp1                        ;yes, then exit
              mov request_flag,0            ;clear request flag
              call directory                ;execute directory routine
bp1:          iret                          ;done - exit
backproc      endp
;
;------------------------------------------------------------------------------
;Interrupt 24h handling routine.
;------------------------------------------------------------------------------
ioerr         proc near
              sti                           ;restore interrupts
              mov error_flag,1              ;set external error flag
              mov al,0                      ;tell DOS to ignore the error
              iret                          ;give control back to DOS
ioerr         endp
;
;------------------------------------------------------------------------------
;DIRECTORY is called by other routines to pop up and control the window.
;------------------------------------------------------------------------------
directory     proc near
              mov program_status,1          ;set program active flag
              sti                           ;enable interrupts
              push ax                       ;save registers
              push bx
              push cx
              push dx
              push si
              push di
              push ds
              push es
              push cs                       ;set DS to the code segment
              pop ds
              assume ds:code
              push cs                       ;set ES to the code segment
              pop es
;
;Make sure the current video mode is a text mode.
;
              mov ah,15                     ;get video mode and page
              int 10h
              cmp al,2                      ;mode 2?
              je dir1                       ;yes, then continue
              cmp al,3                      ;mode 3?
              je dir1                       ;yes, then continue
              cmp al,7                      ;mode 7?
              je dir1                       ;yes, then continue
exit:         mov program_status,0          ;clear status flag
              pop es                        ;restore registers and exit
              pop ds
              pop di
              pop si
              pop dx
              pop cx
              pop bx
              pop ax
              ret
;
;Save video parameters that must be used now or restored later.
;
dir1:         mov video_page,bh             ;save current video page
              mov ah,3                      ;get cursor mode
              int 10h
              mov cursor_mode,cx            ;save it
              call cursor_address           ;get cursor address from CRTC
              mov cursor_pos,ax             ;save it
              cld                           ;clear DF for string operations
;
;Save the screen contents and open the directory window.
;
              cmp adapter,1                 ;disable video if CGA installed
              jne dir2
              call disable_cga
dir2:         call save_screen              ;save memory to be overwritten
              call open_window              ;draw window to the display
              cmp adapter,1                 ;re-enable CGA video
              jne dir3
              call enable_cga
;
;Set the DTA and interrupt 24h vector to areas inside XDIR.  Then get a
;directory path string from the keyboard.
;
dir3:         call ioset                    ;set DTA and 24h vector
dir4:         mov di,path                   ;point DI to directory path buffer
              mov dx,020Ah                  ;specify input line location
              mov cl,59                     ;specify max length of 59
              call readln                   ;get path string from keyboard
              cmp al,27                     ;was ESC pressed?
              jne dir5                      ;no, then continue
              jmp escape                    ;ESC was pressed - exit
dir5:         push cx                       ;save character count
              mov ah,1                      ;hide the cursor
              mov ch,20h
              int 10h
              pop cx                        ;retrieve count
              mov dx,offset global+1        ;point DX to '*.*' text
              or cl,cl                      ;any characters entered?
              je dir7                       ;yes, then skip ahead
              cmp byte ptr [di-1],'\'       ;is last character a backslash?
              jne dir6                      ;no, then append backslash to path
              dec di                        ;decrement path string pointer
dir6:         lea si,global                 ;append '\*.*' text to path
              mov cx,5
              rep movsb
              mov dx,path                   ;point DX to path string
;
;Read filename information from the specified directory.
;
dir7:         call get_dir                  ;read directory information
              mov dir_page,0                ;initialize page number
              or cx,cx                      ;any files found?
              jne dir9                      ;yes, then continue
;
;No files were found - print message and return to input loop.
;
              mov dx,0721h                  ;set cursor position
              lea si,errtext                ;point SI to error message
              call write_string             ;write error message
              call getkey                   ;wait for a keypress
              call clear_input_line         ;clear input line
              call clear_window             ;then clear the window
              jmp dir4                      ;loop back for another try
;
;One or more files were found.  Display them and look for keystrokes.
;
dir9:         call write_dir                ;write one directory page
dir10:        call getkey                   ;wait for a keypress
              cmp al,0                      ;extended code entered?
              je dir11                      ;yes, then branch to handler
              cmp al,27                     ;ESC pressed?
              jne dir10                     ;no, then ignore keypress
              call clear_input_line         ;clear window and loop back
              call clear_window
              jmp dir4
dir11:        cmp ah,81                     ;PgDn pressed?
              jne dir12                     ;no, then continue testing
              mov al,dir_page               ;last page displayed?
              cmp al,max_page
              je dir10                      ;yes, then ignore keypress
              inc dir_page                  ;advance page number
              call clear_window             ;clear window
              jmp dir9                      ;go back and display new page
dir12:        cmp ah,73                     ;PgUp pressed?
              jne dir10                     ;no, then ignore keypress
              cmp dir_page,0                ;first page displayed?
              je dir10                      ;yes, then ignore keypress
              dec dir_page                  ;update page indicator
              call clear_window             ;clear window
              jmp dir9                      ;loop back
;
;Reset the 24h vector and DTA address, close the window, and exit.
;
escape:       call ioreset                  ;restore DTA and 24h vector
              cmp adapter,1                 ;disable CGA video
              jne esc1
              call disable_cga
esc1:         call restore_screen           ;restore screen contents
              cmp adapter,1                 ;re-enable CGA video
              jne esc2
              call enable_cga
esc2:         mov ah,2                      ;set cursor position
              mov bh,video_page
              mov dx,cursor_pos
              int 10h
              mov ah,1                      ;then unblank the cursor
              mov cx,cursor_mode
              int 10h
              jmp exit                      ;exit
directory     endp
;
;------------------------------------------------------------------------------
;SAVE_SCREEN saves the contents of the screen that underlie the window.
;------------------------------------------------------------------------------
save_screen   proc near
              mov dx,0208h                  ;first window row and column
              mov bl,video_page             ;retrieve active video page
              xor bh,bh                     ;byte to word in BX
              call video_offset             ;determine video memory offset
              mov video_address,di          ;save offset address
              mov si,di                     ;transfer it to SI
              push ds                       ;save DS
              mov ds,video_segment          ;then set it to the video segment
              assume ds:nothing
              mov di,screen_buffer          ;point DI to storage buffer
              mov cx,12                     ;12 lines to save
save1:        push cx                       ;save line count
              mov cx,64                     ;64 characters per line
              rep movsw                     ;transfer one line to storage
              pop cx                        ;retrieve line count
              add si,32                     ;point SI to next video line
              loop save1                    ;loop until all lines are saved
              pop ds                        ;restore DS
              assume ds:code
              ret                           ;exit
save_screen   endp
;
;------------------------------------------------------------------------------
;RESTORE_SCREEN restores the saved contents of video memory.
;------------------------------------------------------------------------------
restore_screen proc near
              push es                       ;save ES register value
              mov di,video_address          ;point DI to starting video offset
              mov es,video_segment          ;point ES to video memory
              mov si,screen_buffer          ;point SI to storage buffer
              mov cx,12                     ;12 lines to restore
restore1:     push cx                       ;save line count
              mov cx,64                     ;64 characters per line
              rep movsw                     ;restore one line
              pop cx                        ;retrieve line count
              add di,32                     ;set DI to next video line
              loop restore1                 ;loop until done
              pop es                        ;restore ES
              ret
restore_screen endp
;
;------------------------------------------------------------------------------
;VIDEO_OFFSET calculates the offset address in video memory that corresponds
;to the indicated row, column, and video page.
;Entry:  DH,DL - row, column           | Exit:  DI - offset
;        BX    - video page            |
;------------------------------------------------------------------------------
video_offset  proc near
              mov al,160                    ;row * 160
              mul dh
              shl dl,1                      ;column * 2
              xor dh,dh                     ;byte to word in DX
              add ax,dx                     ;add the results
              mov di,ax                     ;save result in DI
              mov ax,1000h                  ;length of one video page
              mul bx                        ;page * 1000h
              add di,ax                     ;add result to DI
              ret
video_offset  endp
;
;------------------------------------------------------------------------------
;DISABLE_CGA and ENABLE_CGA disable and enable CGA video output.
;------------------------------------------------------------------------------
disable_cga   proc near
              mov dx,3DAh                   ;address of Status Register
disable1:     in al,dx                      ;get status
              test al,8                     ;vertical retrace active?
              je disable1                   ;no, then wait
              sub dx,2                      ;MSR address in DX
              mov al,25h                    ;value to disable video
              out dx,al                     ;disable video output
              ret
disable_cga   endp
;
enable_cga    proc near
              mov ah,15                     ;get video mode
              int 10h
              lea bx,enable_values          ;get value to enable display
              xlat                          ;value in AL
              mov dx,3D8h                   ;MSR address
              out dx,al                     ;enable video output
              ret
enable_cga    endp
;
;------------------------------------------------------------------------------
;KB_RESET resets the keyboard and issues an EOI to the 8259 PIC.
;------------------------------------------------------------------------------
kb_reset      proc near
              in al,61h                     ;get current control value
              mov ah,al                     ;save it in AH
              or al,80h                     ;set the high bit
              out 61h,al                    ;send it to the control port
              mov al,ah                     ;recover original value
              out 61h,al                    ;send it out
              cli                           ;suspend interrupts
              mov al,20h                    ;load EOI value
              out 20h,al                    ;send it to the 8259
              sti                           ;restore interrupts
              ret
kb_reset      endp
;
;------------------------------------------------------------------------------
;SHOW_CURSOR sets the cursor to its default state.
;------------------------------------------------------------------------------
show_cursor   proc near
              mov ah,1                      ;interrupt 10h service 1
              mov cx,default_cursor         ;set scan line definition
              int 10h                       ;set cursor shape
              ret
show_cursor   endp
;
;------------------------------------------------------------------------------
;CURSOR_ADDRESS reads the current cursor position from the video controller.
;------------------------------------------------------------------------------
cursor_address proc near
              mov dx,addr_6845              ;get CRTC Address Register port
              mov al,14                     ;OUT register number
              out dx,al
              inc dx                        ;point DX to Data Register
              in al,dx                      ;read high byte of cursor address
              mov ah,al                     ;save it in AH
              dec dx                        ;point DX back to Address Register
              mov al,15                     ;OUT next register number
              out dx,al
              inc dx                        ;point DX to Data Register
              in al,dx                      ;read low byte of address
              and ax,07FFh                  ;strip 'page' bits from address
              mov bl,80                     ;then divide by 80
              div bl
              xchg ah,al                    ;reverse bytes for proper form
              ret
cursor_address endp
;
;------------------------------------------------------------------------------
;GETKEY waits for a keypress and returns the keycode in AX.
;Exit:  AX - keycode
;------------------------------------------------------------------------------
getkey        proc near
              mov ah,1                      ;check keyboard buffer
              int 16h
              jne getkey1                   ;jump if buffer contains a keycode
              int 28h                       ;no key pressed - issue int 28h
              jmp getkey                    ;loop back to try again
getkey1:      mov ah,0                      ;get keycode from buffer
              int 16h
              ret                           ;exit with keycode in AX
getkey        endp
;
;------------------------------------------------------------------------------
;OPEN_WINDOW writes the blank directory window to display memory.
;------------------------------------------------------------------------------
open_window   proc near
              push es                       ;save ES
              mov es,video_segment          ;set ES:DI to video memory
              mov di,video_address
              mov al,218                    ;write first character
              mov ah,border_attr
              stosw
              mov cx,62                     ;then do the next 62
              mov al,32
              rep stosw
              mov al,191                    ;finish the first line
              stosw
              add di,32                     ;set DI to start of next line
              mov cx,10                     ;10 lines to do
open1:        push cx                       ;save line counter
              mov al,179                    ;write first character on line
              mov ah,border_attr
              push ax                       ;save character/attribute pair
              stosw                         ;write them to video memory
              mov cx,62                     ;write next 62 characters
              mov al,32
              mov ah,text_attr
              rep stosw
              pop ax                        ;retrieve saved word for final char
              stosw                         ;finish the line
              add di,32                     ;set DI to start of next line
              pop cx                        ;retrieve line counter
              loop open1                    ;loop until 10 lines are done
              mov al,192                    ;first character of last line
              stosw
              mov cx,62                     ;write the next 62 characters
              mov al,196
              rep stosw
              mov al,217                    ;finish the last line
              stosw
              pop es                        ;restore ES
              ret
open_window   endp
;
;------------------------------------------------------------------------------
;READLN accepts input of a string entered from the keyboard.
;Entry:  ES:DI - buffer address        | Exit: CL - string length
;        DH,DL - cursor start position |
;        CL    - max length accepted   |
;------------------------------------------------------------------------------
readln        proc near
              mov maxlen,cl                 ;save max length
              mov ah,2                      ;set cursor to start position
              mov bh,video_page
              int 10h
              call show_cursor              ;make sure cursor is visible
              xor cl,cl                     ;initialize counter
read1:        call getkey                   ;get a character
              cmp al,13                     ;ENTER key?
              je read_exit                  ;yes, then exit
              cmp al,27                     ;ESC key?
              je read_exit                  ;yes, then exit
              cmp al,8                      ;backspace key?
              je backspace                  ;yes, then do backspace function
              cmp al,32                     ;ASCII 32 or greater?
              jb read1                      ;no, then ignore it
              cmp cl,maxlen                 ;room for another entry?
              je read1                      ;no, then ignore it
              push ax                       ;save character just entered
              push cx                       ;save character count
              mov ah,10                     ;print the character
              mov cx,1
              int 10h
              inc dl                        ;advance the cursor
              mov ah,2
              int 10h
              pop cx                        ;retrieve count
              pop ax                        ;retrieve character
              stosb                         ;deposit entry in buffer
              inc cl                        ;update count
              jmp read1                     ;go back for more
backspace:    or cl,cl                      ;any characters to delete?
              je read1                      ;no, then ignore keystroke
              push cx                       ;save count
              dec dl                        ;move cursor back one space
              mov ah,2
              int 10h
              mov ah,10                     ;print a space character
              mov al,32
              mov cx,1
              int 10h
              pop cx                        ;retrieve count
              dec cl                        ;decrement it
              dec di                        ;decrement buffer pointer
              jmp read1                     ;go back for more
read_exit:    ret                           ;exit
readln        endp
;
;------------------------------------------------------------------------------
;IOSET saves the current DTA address and interrupt 24h vector, then replaces
;them with pointers to XDIR routines.  IORESET restores the original values.
;------------------------------------------------------------------------------
ioset         proc near
              push es                       ;save ES
              mov ah,2Fh                    ;get current DTA address
              int 21h
              mov old_dta_segment,es        ;save it
              mov old_dta_offset,bx
              mov ah,1Ah                    ;set new DTA address
              mov dx,dta
              int 21h
              mov ah,35h                    ;get interrupt 24h vector
              mov al,24h
              int 21h
              mov old24h_segment,es         ;save it
              mov old24h_offset,bx
              mov ah,25h                    ;then set it to IOERR routine
              lea dx,ioerr
              int 21h
              pop es                        ;restore ES
              ret
ioset         endp
;
ioreset       proc near
              mov ah,25h                    ;restore interrupt 24h vector
              mov al,24h
              mov dx,old24h_offset
              push ds
              assume ds:nothing
              mov ds,old24h_segment
              int 21h
              mov ah,1Ah                    ;restore original DTA address
              mov dx,old_dta_offset
              mov ds,old_dta_segment
              int 21h
              pop ds
              assume ds:code
              ret
ioreset       endp
;
;------------------------------------------------------------------------------
;GET_DIR reads the specified directory and stores the ASCIIZ filename text.
;Entry:  DS:DX - pathname              | Exit:  CX - number of files
;------------------------------------------------------------------------------
get_dir       proc near
              mov error_flag,0              ;initialize critical error flag
              mov ah,4Eh                    ;find first filename
              mov cx,search_attr            ;set search attribute
              int 21h                       ;initiate file search
              mov cx,0                      ;zero CX in case no files found
              jc getdir4                    ;done if no files found
              cmp error_flag,0              ;critical error flag clear?
              jne getdir4                   ;no, then exit immediately
              inc cx                        ;initialize file count
              mov di,text_buffer            ;set buffer address
              call copy_filename            ;copy filename to buffer
getdir1:      mov ah,4Fh                    ;continue file search
              int 21h
              jc getdir2                    ;done if nothing found
              cmp error_flag,0              ;did a critical error occur?
              jne getdir2                   ;yes, then exit
              call copy_filename            ;copy next filename
              inc cx                        ;update counter
              cmp cx,360                    ;buffer full?
              jne getdir1                   ;no, go back for more
getdir2:      sub di,13                     ;go back to start of last filename
getdir3:      inc di                        ;point DI to next byte
              cmp byte ptr es:[di],0        ;is this a zero byte?
              jne getdir3                   ;no, then advance to next byte
              dec byte ptr es:[di]          ;mark end of text with a 255
              mov ax,cx                     ;calculate number of pages
              dec ax
              mov bl,40
              div bl
              mov max_page,al               ;save highest page number
getdir4:      ret
get_dir       endp
;
;------------------------------------------------------------------------------
;COPY_FILENAME copies an ASCIIZ filename from the DTA to the indicated address.
;Entry:  ES:DI - destination address
;------------------------------------------------------------------------------
copy_filename proc near
              mov si,dta                    ;get DTA address
              add si,30                     ;point SI to start of filename
              push cx                       ;save CX
              mov cx,13                     ;filename length is 13 bytes
              rep movsb                     ;copy filename to storage
              pop cx                        ;restore entry value of CX
              ret
copy_filename endp
;
;------------------------------------------------------------------------------
;WRITE_DIR writes one page of directory data to the directory window.
;------------------------------------------------------------------------------
write_dir     proc near
              mov end_flag,0                ;initialize END_FLAG
              mov ax,520                    ;520 bytes per directory page
              mov bl,dir_page               ;get page number in BL
              xor bh,bh                     ;byte to word in BX
              mul bx                        ;find offset into TEXT_BUFFER
              mov si,ax                     ;transfer offset to SI
              add si,text_buffer            ;complete address calculation
              mov dx,030Ah                  ;specify starting cursor position
              mov cx,10                     ;do 10 lines
wdir4:        push cx                       ;save line counter
              call write_line               ;write one line
              inc dh                        ;set cursor to next line
              mov dl,10
              pop cx                        ;restore line count
              cmp end_flag,0                ;END_FLAG set?
              jne wdir5                     ;yes, then terminate
              loop wdir4                    ;loop until all lines are done
wdir5:        ret
write_dir     endp
;
;------------------------------------------------------------------------------
;WRITE_LINE writes a single line of directory text to the display.
;Entry:  DH,DL - starting row and column
;------------------------------------------------------------------------------
write_line    proc near
              mov cx,4                      ;4 entries per line
wline1:       push cx                       ;save counter
              push si                       ;save text address
              push dx                       ;save cursor address
              call write_string             ;write one entry
              pop dx                        ;retrieve cursor address
              add dl,16                     ;set cursor to next field
              pop si                        ;retrieve text address
              add si,13                     ;set it for next write
              pop cx                        ;retrieve count
              cmp end_flag,0                ;END_FLAG set?
              jne wline2                    ;yes, then exit
              loop wline1                   ;loop until done
wline2:       ret
write_line    endp
;
;------------------------------------------------------------------------------
;WRITE_STRING writes an ASCIIZ string to the display.
;Entry:  DH,DL - starting row and column
;        DS:SI - string address
;------------------------------------------------------------------------------
write_string  proc near
              mov ah,2                      ;set cursor to start position
              mov bh,video_page
              int 10h
              mov cx,1                      ;output one character at a time
write1:       lodsb                         ;get a character
              or al,al                      ;is it a zero?
              je write3                     ;yes, then exit
              cmp al,255                    ;is it 255?
              je write2                     ;yes, then set END_FLAG and exit
              mov ah,10                     ;print character
              int 10h
              mov ah,2                      ;advance cursor
              inc dl
              int 10h
              jmp write1                    ;loop until done
write2:       mov end_flag,1                ;set END_FLAG
write3:       ret
write_string  endp
;
;------------------------------------------------------------------------------
;CLEAR_WINDOW clears the contents of the directory window.
;------------------------------------------------------------------------------
clear_window  proc near
              mov ah,6                      ;clear window with BIOS routine
              mov al,0                      ;specify clear function
              mov cx,030Ah                  ;specify window coordinates
              mov dx,0C45h
              mov bh,text_attr              ;attribute to be used
              int 10h
              ret
clear_window  endp
;
;------------------------------------------------------------------------------
;CLEAR_INPUT_LINE clears the window input line.
;------------------------------------------------------------------------------
clear_input_line proc near
              mov ah,2                      ;set cursor to start of input line
              mov dx,020Ah
              mov bh,video_page
              int 10h
              mov ah,10                     ;then write a string of spaces
              mov al,32
              mov cx,60
              int 10h
              ret
clear_input_line endp
;
;------------------------------------------------------------------------------
;INITIALIZE prepares the program for residency.
;------------------------------------------------------------------------------
initialize    proc near
;
;Determine what type of video adapter is installed.
;
              mov ah,12h                    ;prepare for call to int 10h
              mov bl,10h                    ;function - request EGA info
              int 10h
              cmp bl,10h                    ;BL=10h?
              je init1                      ;yes, then no EGA installed
              or bh,bh                      ;BH=0?
              jne init2                     ;no, then it's a monochrome system
              jmp init3
init1:        dec adapter                   ;decrement ADAPTER value
              mov ah,15                     ;get video mode
              int 10h
              cmp al,7                      ;is it mode 7?
              jne init3                     ;no, then it's a color system
              dec adapter                   ;set ADAPTER to 0
;
;Modify video parameter values for monochrome, then initialize the cursor.
;
init2:        sub video_segment,800h        ;set VIDEO_SEGMENT for monochrome
              mov border_attr,70h           ;change attributes for monochrome
              mov text_attr,07h
              mov default_cursor,0C0Dh      ;set monochrome cursor definition
init3:        call show_cursor              ;set cursor to default mode
;
;Determine the port address of the CRT Controller and store it.
;
              mov ax,40h                    ;point ES to BIOS data segment
              mov es,ax
              mov di,63h                    ;point DI to address word
              mov dx,es:[di]                ;get CRTC address
              mov addr_6845,dx              ;save it
;
;Get and save the address of the DOS BUSY_FLAG.
;
              mov ah,34h                    ;function 34h
              int 21h                       ;get address
              mov dos_segment,es            ;save segment
              mov busy_flag,bx              ;save offset
;
;Save and replace all required interrupt vectors.
;
              mov ah,35h                    ;get interrupt 9 vector
              mov al,9
              int 21h
              mov old9h,bx                  ;save it
              mov old9h[2],es
              mov ah,25h                    ;point it to KEYBOARD routine
              lea dx,keyboard
              int 21h
              mov ah,35h                    ;get interrupt 1Ch vector
	      mov al,8 ;patched vh
              int 21h
              mov old1ch,bx                 ;save it
              mov old1ch[2],es
              mov ah,25h                    ;then point it to TIMER
              lea dx,timer
              int 21h
              mov ah,35h                    ;get interrupt 13h vector
              mov al,13h
              int 21h
              mov old13h,bx                 ;save it
              mov old13h[2],es
              mov ah,25h                    ;point it to BDISK
              lea dx,bdisk
              int 21h
              mov ah,35h                    ;get interrupt 28h vector
              mov al,28h
              int 21h
              mov old28h,bx                 ;save it
              mov old28h[2],es
              mov ah,25h                    ;point it to BACKPROC
              lea dx,backproc
              int 21h
;
;Terminate but remain resident in memory.
;
              mov dx,offset initialize+6216 ;point DX to end of resident code
              int 27h                       ;terminate-but-stay-resident
initialize    endp
;
code          ends
              end begin


[ RETURN TO DIRECTORY ]