home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / dirutl / xdir.arc / XDIR.ASM next >
Assembly Source File  |  1987-03-18  |  32KB  |  816 lines

  1. ;XDIR.COM for the IBM Personal Computer - 1986 by Jeff Prosise
  2. code          segment para public 'code'
  3.           assume cs:code
  4.           org 100h
  5. begin:          jmp initialize            ;goto initialization code
  6. ;
  7. copyright       db 'Copyright 1986 Ziff-Davis Publishing Co.',1Ah
  8. global           db '\*.*',0              ;global directory filespec
  9. dos_segment       dw ?             ;DOS segment
  10. busy_flag       dw ?             ;offset of DOS BUSY_FLAG
  11. program_status       db 0             ;XDIR processing status
  12. flag_13h       db 0             ;status of interrupt 13h
  13. request_flag       db 0             ;status of processing request
  14. adapter        db 2             ;0 = MDA, 1 = CGA, 2 = EGA
  15. video_segment       dw 0B800h            ;video segment address
  16. video_page       db ?             ;current video page
  17. border_attr       db 4Fh            ;window border attribute
  18. text_attr       db 0Fh            ;window text attribute
  19. video_address       dw ?             ;window start address
  20. cursor_mode       dw ?             ;cursor shape
  21. cursor_pos       dw ?             ;cursor position
  22. maxlen           db ?             ;maximum input string length
  23. max_page       db ?             ;number of highest directory page
  24. dir_page       db ?             ;current directory page
  25. end_flag       db ?             ;status of text write routines
  26. error_flag       db ?             ;critical error status
  27. default_cursor       dw 0607h            ;default cursor shape (color)
  28. addr_6845       dw ?             ;CRT Controller base address
  29. search_attr       dw 0             ;file search attribute
  30. ;
  31. path           dw 0              ;pointer to pathname buffer
  32. dta           dw 64             ;pointer to Disk Transfer Area
  33. screen_buffer       dw offset initialize      ;pointer to screen buffer
  34. text_buffer       dw offset initialize+1536     ;pointer to filename buffer
  35. ;
  36. keyboard_int       label dword            ;old interrupt 9 vector
  37. old9h           dw 2 dup (?)
  38. timer_int       label dword            ;old interrupt 1Ch vector
  39. old1ch           dw 2 dup (?)
  40. bdisk_int       label dword            ;old interrupt 13h vector
  41. old13h           dw 2 dup (?)
  42. bp_int           label dword            ;old interrupt 28h vector
  43. old28h           dw 2 dup (?)
  44. ;
  45. old_dta_segment    dw ?             ;old DTA segment address
  46. old_dta_offset       dw ?             ;old DTA offset address
  47. old24h_segment       dw ?             ;old interrupt 24h routine segment
  48. old24h_offset       dw ?             ;old interrupt 24h routine offset
  49. enable_values       db 2Ch,28h,2Dh,29h        ;values to enable CGA output
  50.            db 2Ah,2Eh,1Eh
  51. errtext        db 'No Files Found',0
  52. ;
  53. ;------------------------------------------------------------------------------
  54. ;Execution comes here thru interrupt 9 every time a key is pressed or released.
  55. ;------------------------------------------------------------------------------
  56. keyboard      proc near
  57.           sti                ;set interrupt enable flag
  58.           push ax                ;save AX
  59.           in al,60h             ;get scan code from keyboard
  60.           cmp al,52             ;was the '.' key pressed?
  61.           jne kb2                ;no, then exit to normal handler
  62.           mov ah,2                ;check shift key status
  63.           int 16h
  64.           test al,8             ;is the Alt key pressed?
  65.           je kb2                ;no, then exit
  66.           call kb_reset            ;reset keyboard, issue EOI
  67.           pop ax                ;restore AX
  68.           cmp program_status,0        ;XDIR routine already active?
  69.           jne kb1                ;yes, then don't set request flag
  70.           mov request_flag,1        ;set request flag
  71. kb1:          iret                ;end interrupt routine
  72. kb2:          pop ax                ;restore AX
  73.           jmp keyboard_int            ;goto original keyboard routine
  74. keyboard      endp
  75. ;
  76. ;------------------------------------------------------------------------------
  77. ;Interrupt 1Ch handling routine.
  78. ;------------------------------------------------------------------------------
  79. timer          proc near
  80.           pushf                ;call original routine
  81.           call timer_int
  82.           cmp request_flag,0        ;request flag set?
  83.           je timer1             ;no, then exit
  84.           push es                ;save ES and DI
  85.           push di
  86.           mov es,dos_segment        ;get DOS segment in ES
  87.           mov di,busy_flag            ;address of DOS BUSY_FLAG in DI
  88.           cmp byte ptr es:[di],0        ;DOS service currently active?
  89.           pop di                ;clean up the stack
  90.           pop es
  91.           jne timer1            ;yes, then we must wait
  92.           cmp flag_13h,0            ;BIOS disk service active?
  93.           jne timer1            ;yes, then don't interrupt it
  94.           mov al,20h            ;issue EOI to 8259 PIC
  95.           out 20h,al
  96.           mov request_flag,0        ;reset request flag
  97.           call directory            ;invoke directory routine
  98. timer1:       iret                ;done - exit
  99. timer          endp
  100. ;
  101. ;------------------------------------------------------------------------------
  102. ;Interrupt 13h handling routine.
  103. ;------------------------------------------------------------------------------
  104. bdisk          proc near
  105.           inc flag_13h            ;set 'busy' flag
  106.           pushf                ;call original routine
  107.           call bdisk_int
  108.           dec flag_13h            ;clear flag
  109.           iret
  110. bdisk          endp
  111. ;
  112. ;------------------------------------------------------------------------------
  113. ;Interrupt 28h handling routine.
  114. ;------------------------------------------------------------------------------
  115. backproc      proc near
  116.           pushf                ;call original routine
  117.           call bp_int
  118.           cmp request_flag,0        ;request flag clear?
  119.           je bp1                ;yes, then exit
  120.           mov request_flag,0        ;clear request flag
  121.           call directory            ;execute directory routine
  122. bp1:          iret                ;done - exit
  123. backproc      endp
  124. ;
  125. ;------------------------------------------------------------------------------
  126. ;Interrupt 24h handling routine.
  127. ;------------------------------------------------------------------------------
  128. ioerr          proc near
  129.           sti                ;restore interrupts
  130.           mov error_flag,1            ;set external error flag
  131.           mov al,0                ;tell DOS to ignore the error
  132.           iret                ;give control back to DOS
  133. ioerr          endp
  134. ;
  135. ;------------------------------------------------------------------------------
  136. ;DIRECTORY is called by other routines to pop up and control the window.
  137. ;------------------------------------------------------------------------------
  138. directory     proc near
  139.           mov program_status,1        ;set program active flag
  140.           sti                ;enable interrupts
  141.           push ax                ;save registers
  142.           push bx
  143.           push cx
  144.           push dx
  145.           push si
  146.           push di
  147.           push ds
  148.           push es
  149.           push cs                ;set DS to the code segment
  150.           pop ds
  151.           assume ds:code
  152.           push cs                ;set ES to the code segment
  153.           pop es
  154. ;
  155. ;Make sure the current video mode is a text mode.
  156. ;
  157.           mov ah,15             ;get video mode and page
  158.           int 10h
  159.           cmp al,2                ;mode 2?
  160.           je dir1                ;yes, then continue
  161.           cmp al,3                ;mode 3?
  162.           je dir1                ;yes, then continue
  163.           cmp al,7                ;mode 7?
  164.           je dir1                ;yes, then continue
  165. exit:          mov program_status,0        ;clear status flag
  166.           pop es                ;restore registers and exit
  167.           pop ds
  168.           pop di
  169.           pop si
  170.           pop dx
  171.           pop cx
  172.           pop bx
  173.           pop ax
  174.           ret
  175. ;
  176. ;Save video parameters that must be used now or restored later.
  177. ;
  178. dir1:          mov video_page,bh         ;save current video page
  179.           mov ah,3                ;get cursor mode
  180.           int 10h
  181.           mov cursor_mode,cx        ;save it
  182.           call cursor_address        ;get cursor address from CRTC
  183.           mov cursor_pos,ax         ;save it
  184.           cld                ;clear DF for string operations
  185. ;
  186. ;Save the screen contents and open the directory window.
  187. ;
  188.           cmp adapter,1            ;disable video if CGA installed
  189.           jne dir2
  190.           call disable_cga
  191. dir2:          call save_screen            ;save memory to be overwritten
  192.           call open_window            ;draw window to the display
  193.           cmp adapter,1            ;re-enable CGA video
  194.           jne dir3
  195.           call enable_cga
  196. ;
  197. ;Set the DTA and interrupt 24h vector to areas inside XDIR.  Then get a
  198. ;directory path string from the keyboard.
  199. ;
  200. dir3:          call ioset            ;set DTA and 24h vector
  201. dir4:          mov di,path            ;point DI to directory path buffer
  202.           mov dx,020Ah            ;specify input line location
  203.           mov cl,59             ;specify max length of 59
  204.           call readln            ;get path string from keyboard
  205.           cmp al,27             ;was ESC pressed?
  206.           jne dir5                ;no, then continue
  207.           jmp escape            ;ESC was pressed - exit
  208. dir5:          push cx                ;save character count
  209.           mov ah,1                ;hide the cursor
  210.           mov ch,20h
  211.           int 10h
  212.           pop cx                ;retrieve count
  213.           mov dx,offset global+1        ;point DX to '*.*' text
  214.           or cl,cl                ;any characters entered?
  215.           je dir7                ;yes, then skip ahead
  216.           cmp byte ptr [di-1],'\'       ;is last character a backslash?
  217.           jne dir6                ;no, then append backslash to path
  218.           dec di                ;decrement path string pointer
  219. dir6:          lea si,global            ;append '\*.*' text to path
  220.           mov cx,5
  221.           rep movsb
  222.           mov dx,path            ;point DX to path string
  223. ;
  224. ;Read filename information from the specified directory.
  225. ;
  226. dir7:          call get_dir            ;read directory information
  227.           mov dir_page,0            ;initialize page number
  228.           or cx,cx                ;any files found?
  229.           jne dir9                ;yes, then continue
  230. ;
  231. ;No files were found - print message and return to input loop.
  232. ;
  233.           mov dx,0721h            ;set cursor position
  234.           lea si,errtext            ;point SI to error message
  235.           call write_string         ;write error message
  236.           call getkey            ;wait for a keypress
  237.           call clear_input_line        ;clear input line
  238.           call clear_window         ;then clear the window
  239.           jmp dir4                ;loop back for another try
  240. ;
  241. ;One or more files were found.    Display them and look for keystrokes.
  242. ;
  243. dir9:          call write_dir            ;write one directory page
  244. dir10:          call getkey            ;wait for a keypress
  245.           cmp al,0                ;extended code entered?
  246.           je dir11                ;yes, then branch to handler
  247.           cmp al,27             ;ESC pressed?
  248.           jne dir10             ;no, then ignore keypress
  249.           call clear_input_line        ;clear window and loop back
  250.           call clear_window
  251.           jmp dir4
  252. dir11:          cmp ah,81             ;PgDn pressed?
  253.           jne dir12             ;no, then continue testing
  254.           mov al,dir_page            ;last page displayed?
  255.           cmp al,max_page
  256.           je dir10                ;yes, then ignore keypress
  257.           inc dir_page            ;advance page number
  258.           call clear_window         ;clear window
  259.           jmp dir9                ;go back and display new page
  260. dir12:          cmp ah,73             ;PgUp pressed?
  261.           jne dir10             ;no, then ignore keypress
  262.           cmp dir_page,0            ;first page displayed?
  263.           je dir10                ;yes, then ignore keypress
  264.           dec dir_page            ;update page indicator
  265.           call clear_window         ;clear window
  266.           jmp dir9                ;loop back
  267. ;
  268. ;Reset the 24h vector and DTA address, close the window, and exit.
  269. ;
  270. escape:       call ioreset            ;restore DTA and 24h vector
  271.           cmp adapter,1            ;disable CGA video
  272.           jne esc1
  273.           call disable_cga
  274. esc1:          call restore_screen        ;restore screen contents
  275.           cmp adapter,1            ;re-enable CGA video
  276.           jne esc2
  277.           call enable_cga
  278. esc2:          mov ah,2                ;set cursor position
  279.           mov bh,video_page
  280.           mov dx,cursor_pos
  281.           int 10h
  282.           mov ah,1                ;then unblank the cursor
  283.           mov cx,cursor_mode
  284.           int 10h
  285.           jmp exit                ;exit
  286. directory     endp
  287. ;
  288. ;------------------------------------------------------------------------------
  289. ;SAVE_SCREEN saves the contents of the screen that underlie the window.
  290. ;------------------------------------------------------------------------------
  291. save_screen   proc near
  292.           mov dx,0208h            ;first window row and column
  293.           mov bl,video_page         ;retrieve active video page
  294.           xor bh,bh             ;byte to word in BX
  295.           call video_offset         ;determine video memory offset
  296.           mov video_address,di        ;save offset address
  297.           mov si,di             ;transfer it to SI
  298.           push ds                ;save DS
  299.           mov ds,video_segment        ;then set it to the video segment
  300.           assume ds:nothing
  301.           mov di,screen_buffer        ;point DI to storage buffer
  302.           mov cx,12             ;12 lines to save
  303. save1:          push cx                ;save line count
  304.           mov cx,64             ;64 characters per line
  305.           rep movsw             ;transfer one line to storage
  306.           pop cx                ;retrieve line count
  307.           add si,32             ;point SI to next video line
  308.           loop save1            ;loop until all lines are saved
  309.           pop ds                ;restore DS
  310.           assume ds:code
  311.           ret                ;exit
  312. save_screen   endp
  313. ;
  314. ;------------------------------------------------------------------------------
  315. ;RESTORE_SCREEN restores the saved contents of video memory.
  316. ;------------------------------------------------------------------------------
  317. restore_screen proc near
  318.           push es                ;save ES register value
  319.           mov di,video_address        ;point DI to starting video offset
  320.           mov es,video_segment        ;point ES to video memory
  321.           mov si,screen_buffer        ;point SI to storage buffer
  322.           mov cx,12             ;12 lines to restore
  323. restore1:     push cx                ;save line count
  324.           mov cx,64             ;64 characters per line
  325.           rep movsw             ;restore one line
  326.           pop cx                ;retrieve line count
  327.           add di,32             ;set DI to next video line
  328.           loop restore1            ;loop until done
  329.           pop es                ;restore ES
  330.           ret
  331. restore_screen endp
  332. ;
  333. ;------------------------------------------------------------------------------
  334. ;VIDEO_OFFSET calculates the offset address in video memory that corresponds
  335. ;to the indicated row, column, and video page.
  336. ;Entry:  DH,DL - row, column           | Exit:    DI - offset
  337. ;     BX    - video page           |
  338. ;------------------------------------------------------------------------------
  339. video_offset  proc near
  340.           mov al,160            ;row * 160
  341.           mul dh
  342.           shl dl,1                ;column * 2
  343.           xor dh,dh             ;byte to word in DX
  344.           add ax,dx             ;add the results
  345.           mov di,ax             ;save result in DI
  346.           mov ax,1000h            ;length of one video page
  347.           mul bx                ;page * 1000h
  348.           add di,ax             ;add result to DI
  349.           ret
  350. video_offset  endp
  351. ;
  352. ;------------------------------------------------------------------------------
  353. ;DISABLE_CGA and ENABLE_CGA disable and enable CGA video output.
  354. ;------------------------------------------------------------------------------
  355. disable_cga   proc near
  356.           mov dx,3DAh            ;address of Status Register
  357. disable1:     in al,dx                ;get status
  358.           test al,8             ;vertical retrace active?
  359.           je disable1            ;no, then wait
  360.           sub dx,2                ;MSR address in DX
  361.           mov al,25h            ;value to disable video
  362.           out dx,al             ;disable video output
  363.           ret
  364. disable_cga   endp
  365. ;
  366. enable_cga    proc near
  367.           mov ah,15             ;get video mode
  368.           int 10h
  369.           lea bx,enable_values        ;get value to enable display
  370.           xlat                ;value in AL
  371.           mov dx,3D8h            ;MSR address
  372.           out dx,al             ;enable video output
  373.           ret
  374. enable_cga    endp
  375. ;
  376. ;------------------------------------------------------------------------------
  377. ;KB_RESET resets the keyboard and issues an EOI to the 8259 PIC.
  378. ;------------------------------------------------------------------------------
  379. kb_reset      proc near
  380.           in al,61h             ;get current control value
  381.           mov ah,al             ;save it in AH
  382.           or al,80h             ;set the high bit
  383.           out 61h,al            ;send it to the control port
  384.           mov al,ah             ;recover original value
  385.           out 61h,al            ;send it out
  386.           cli                ;suspend interrupts
  387.           mov al,20h            ;load EOI value
  388.           out 20h,al            ;send it to the 8259
  389.           sti                ;restore interrupts
  390.           ret
  391. kb_reset      endp
  392. ;
  393. ;------------------------------------------------------------------------------
  394. ;SHOW_CURSOR sets the cursor to its default state.
  395. ;------------------------------------------------------------------------------
  396. show_cursor   proc near
  397.           mov ah,1                ;interrupt 10h service 1
  398.           mov cx,default_cursor        ;set scan line definition
  399.           int 10h                ;set cursor shape
  400.           ret
  401. show_cursor   endp
  402. ;
  403. ;------------------------------------------------------------------------------
  404. ;CURSOR_ADDRESS reads the current cursor position from the video controller.
  405. ;------------------------------------------------------------------------------
  406. cursor_address proc near
  407.           mov dx,addr_6845            ;get CRTC Address Register port
  408.           mov al,14             ;OUT register number
  409.           out dx,al
  410.           inc dx                ;point DX to Data Register
  411.           in al,dx                ;read high byte of cursor address
  412.           mov ah,al             ;save it in AH
  413.           dec dx                ;point DX back to Address Register
  414.           mov al,15             ;OUT next register number
  415.           out dx,al
  416.           inc dx                ;point DX to Data Register
  417.           in al,dx                ;read low byte of address
  418.           and ax,07FFh            ;strip 'page' bits from address
  419.           mov bl,80             ;then divide by 80
  420.           div bl
  421.           xchg ah,al            ;reverse bytes for proper form
  422.           ret
  423. cursor_address endp
  424. ;
  425. ;------------------------------------------------------------------------------
  426. ;GETKEY waits for a keypress and returns the keycode in AX.
  427. ;Exit:    AX - keycode
  428. ;------------------------------------------------------------------------------
  429. getkey          proc near
  430.           mov ah,1                ;check keyboard buffer
  431.           int 16h
  432.           jne getkey1            ;jump if buffer contains a keycode
  433.           int 28h                ;no key pressed - issue int 28h
  434.           jmp getkey            ;loop back to try again
  435. getkey1:      mov ah,0                ;get keycode from buffer
  436.           int 16h
  437.           ret                ;exit with keycode in AX
  438. getkey          endp
  439. ;
  440. ;------------------------------------------------------------------------------
  441. ;OPEN_WINDOW writes the blank directory window to display memory.
  442. ;------------------------------------------------------------------------------
  443. open_window   proc near
  444.           push es                ;save ES
  445.           mov es,video_segment        ;set ES:DI to video memory
  446.           mov di,video_address
  447.           mov al,218            ;write first character
  448.           mov ah,border_attr
  449.           stosw
  450.           mov cx,62             ;then do the next 62
  451.           mov al,32
  452.           rep stosw
  453.           mov al,191            ;finish the first line
  454.           stosw
  455.           add di,32             ;set DI to start of next line
  456.           mov cx,10             ;10 lines to do
  457. open1:          push cx                ;save line counter
  458.           mov al,179            ;write first character on line
  459.           mov ah,border_attr
  460.           push ax                ;save character/attribute pair
  461.           stosw                ;write them to video memory
  462.           mov cx,62             ;write next 62 characters
  463.           mov al,32
  464.           mov ah,text_attr
  465.           rep stosw
  466.           pop ax                ;retrieve saved word for final char
  467.           stosw                ;finish the line
  468.           add di,32             ;set DI to start of next line
  469.           pop cx                ;retrieve line counter
  470.           loop open1            ;loop until 10 lines are done
  471.           mov al,192            ;first character of last line
  472.           stosw
  473.           mov cx,62             ;write the next 62 characters
  474.           mov al,196
  475.           rep stosw
  476.           mov al,217            ;finish the last line
  477.           stosw
  478.           pop es                ;restore ES
  479.           ret
  480. open_window   endp
  481. ;
  482. ;------------------------------------------------------------------------------
  483. ;READLN accepts input of a string entered from the keyboard.
  484. ;Entry:  ES:DI - buffer address        | Exit: CL - string length
  485. ;     DH,DL - cursor start position |
  486. ;     CL    - max length accepted   |
  487. ;------------------------------------------------------------------------------
  488. readln          proc near
  489.           mov maxlen,cl            ;save max length
  490.           mov ah,2                ;set cursor to start position
  491.           mov bh,video_page
  492.           int 10h
  493.           call show_cursor            ;make sure cursor is visible
  494.           xor cl,cl             ;initialize counter
  495. read1:          call getkey            ;get a character
  496.           cmp al,13             ;ENTER key?
  497.           je read_exit            ;yes, then exit
  498.           cmp al,27             ;ESC key?
  499.           je read_exit            ;yes, then exit
  500.           cmp al,8                ;backspace key?
  501.           je backspace            ;yes, then do backspace function
  502.           cmp al,32             ;ASCII 32 or greater?
  503.           jb read1                ;no, then ignore it
  504.           cmp cl,maxlen            ;room for another entry?
  505.           je read1                ;no, then ignore it
  506.           push ax                ;save character just entered
  507.           push cx                ;save character count
  508.           mov ah,10             ;print the character
  509.           mov cx,1
  510.           int 10h
  511.           inc dl                ;advance the cursor
  512.           mov ah,2
  513.           int 10h
  514.           pop cx                ;retrieve count
  515.           pop ax                ;retrieve character
  516.           stosb                ;deposit entry in buffer
  517.           inc cl                ;update count
  518.           jmp read1             ;go back for more
  519. backspace:    or cl,cl                ;any characters to delete?
  520.           je read1                ;no, then ignore keystroke
  521.           push cx                ;save count
  522.           dec dl                ;move cursor back one space
  523.           mov ah,2
  524.           int 10h
  525.           mov ah,10             ;print a space character
  526.           mov al,32
  527.           mov cx,1
  528.           int 10h
  529.           pop cx                ;retrieve count
  530.           dec cl                ;decrement it
  531.           dec di                ;decrement buffer pointer
  532.           jmp read1             ;go back for more
  533. read_exit:    ret                ;exit
  534. readln          endp
  535. ;
  536. ;------------------------------------------------------------------------------
  537. ;IOSET saves the current DTA address and interrupt 24h vector, then replaces
  538. ;them with pointers to XDIR routines.  IORESET restores the original values.
  539. ;------------------------------------------------------------------------------
  540. ioset          proc near
  541.           push es                ;save ES
  542.           mov ah,2Fh            ;get current DTA address
  543.           int 21h
  544.           mov old_dta_segment,es        ;save it
  545.           mov old_dta_offset,bx
  546.           mov ah,1Ah            ;set new DTA address
  547.           mov dx,dta
  548.           int 21h
  549.           mov ah,35h            ;get interrupt 24h vector
  550.           mov al,24h
  551.           int 21h
  552.           mov old24h_segment,es        ;save it
  553.           mov old24h_offset,bx
  554.           mov ah,25h            ;then set it to IOERR routine
  555.           lea dx,ioerr
  556.           int 21h
  557.           pop es                ;restore ES
  558.           ret
  559. ioset          endp
  560. ;
  561. ioreset       proc near
  562.           mov ah,25h            ;restore interrupt 24h vector
  563.           mov al,24h
  564.           mov dx,old24h_offset
  565.           push ds
  566.           assume ds:nothing
  567.           mov ds,old24h_segment
  568.           int 21h
  569.           mov ah,1Ah            ;restore original DTA address
  570.           mov dx,old_dta_offset
  571.           mov ds,old_dta_segment
  572.           int 21h
  573.           pop ds
  574.           assume ds:code
  575.           ret
  576. ioreset       endp
  577. ;
  578. ;------------------------------------------------------------------------------
  579. ;GET_DIR reads the specified directory and stores the ASCIIZ filename text.
  580. ;Entry:  DS:DX - pathname           | Exit:    CX - number of files
  581. ;------------------------------------------------------------------------------
  582. get_dir       proc near
  583.           mov error_flag,0            ;initialize critical error flag
  584.           mov ah,4Eh            ;find first filename
  585.           mov cx,search_attr        ;set search attribute
  586.           int 21h                ;initiate file search
  587.           mov cx,0                ;zero CX in case no files found
  588.           jc getdir4            ;done if no files found
  589.           cmp error_flag,0            ;critical error flag clear?
  590.           jne getdir4            ;no, then exit immediately
  591.           inc cx                ;initialize file count
  592.           mov di,text_buffer        ;set buffer address
  593.           call copy_filename        ;copy filename to buffer
  594. getdir1:      mov ah,4Fh            ;continue file search
  595.           int 21h
  596.           jc getdir2            ;done if nothing found
  597.           cmp error_flag,0            ;did a critical error occur?
  598.           jne getdir2            ;yes, then exit
  599.           call copy_filename        ;copy next filename
  600.           inc cx                ;update counter
  601.           cmp cx,360            ;buffer full?
  602.           jne getdir1            ;no, go back for more
  603. getdir2:      sub di,13             ;go back to start of last filename
  604. getdir3:      inc di                ;point DI to next byte
  605.           cmp byte ptr es:[di],0        ;is this a zero byte?
  606.           jne getdir3            ;no, then advance to next byte
  607.           dec byte ptr es:[di]        ;mark end of text with a 255
  608.           mov ax,cx             ;calculate number of pages
  609.           dec ax
  610.           mov bl,40
  611.           div bl
  612.           mov max_page,al            ;save highest page number
  613. getdir4:      ret
  614. get_dir       endp
  615. ;
  616. ;------------------------------------------------------------------------------
  617. ;COPY_FILENAME copies an ASCIIZ filename from the DTA to the indicated address.
  618. ;Entry:  ES:DI - destination address
  619. ;------------------------------------------------------------------------------
  620. copy_filename proc near
  621.           mov si,dta            ;get DTA address
  622.           add si,30             ;point SI to start of filename
  623.           push cx                ;save CX
  624.           mov cx,13             ;filename length is 13 bytes
  625.           rep movsb             ;copy filename to storage
  626.           pop cx                ;restore entry value of CX
  627.           ret
  628. copy_filename endp
  629. ;
  630. ;------------------------------------------------------------------------------
  631. ;WRITE_DIR writes one page of directory data to the directory window.
  632. ;------------------------------------------------------------------------------
  633. write_dir     proc near
  634.           mov end_flag,0            ;initialize END_FLAG
  635.           mov ax,520            ;520 bytes per directory page
  636.           mov bl,dir_page            ;get page number in BL
  637.           xor bh,bh             ;byte to word in BX
  638.           mul bx                ;find offset into TEXT_BUFFER
  639.           mov si,ax             ;transfer offset to SI
  640.           add si,text_buffer        ;complete address calculation
  641.           mov dx,030Ah            ;specify starting cursor position
  642.           mov cx,10             ;do 10 lines
  643. wdir4:          push cx                ;save line counter
  644.           call write_line            ;write one line
  645.           inc dh                ;set cursor to next line
  646.           mov dl,10
  647.           pop cx                ;restore line count
  648.           cmp end_flag,0            ;END_FLAG set?
  649.           jne wdir5             ;yes, then terminate
  650.           loop wdir4            ;loop until all lines are done
  651. wdir5:          ret
  652. write_dir     endp
  653. ;
  654. ;------------------------------------------------------------------------------
  655. ;WRITE_LINE writes a single line of directory text to the display.
  656. ;Entry:  DH,DL - starting row and column
  657. ;------------------------------------------------------------------------------
  658. write_line    proc near
  659.           mov cx,4                ;4 entries per line
  660. wline1:       push cx                ;save counter
  661.           push si                ;save text address
  662.           push dx                ;save cursor address
  663.           call write_string         ;write one entry
  664.           pop dx                ;retrieve cursor address
  665.           add dl,16             ;set cursor to next field
  666.           pop si                ;retrieve text address
  667.           add si,13             ;set it for next write
  668.           pop cx                ;retrieve count
  669.           cmp end_flag,0            ;END_FLAG set?
  670.           jne wline2            ;yes, then exit
  671.           loop wline1            ;loop until done
  672. wline2:       ret
  673. write_line    endp
  674. ;
  675. ;------------------------------------------------------------------------------
  676. ;WRITE_STRING writes an ASCIIZ string to the display.
  677. ;Entry:  DH,DL - starting row and column
  678. ;     DS:SI - string address
  679. ;------------------------------------------------------------------------------
  680. write_string  proc near
  681.           mov ah,2                ;set cursor to start position
  682.           mov bh,video_page
  683.           int 10h
  684.           mov cx,1                ;output one character at a time
  685. write1:       lodsb                ;get a character
  686.           or al,al                ;is it a zero?
  687.           je write3             ;yes, then exit
  688.           cmp al,255            ;is it 255?
  689.           je write2             ;yes, then set END_FLAG and exit
  690.           mov ah,10             ;print character
  691.           int 10h
  692.           mov ah,2                ;advance cursor
  693.           inc dl
  694.           int 10h
  695.           jmp write1            ;loop until done
  696. write2:       mov end_flag,1            ;set END_FLAG
  697. write3:       ret
  698. write_string  endp
  699. ;
  700. ;------------------------------------------------------------------------------
  701. ;CLEAR_WINDOW clears the contents of the directory window.
  702. ;------------------------------------------------------------------------------
  703. clear_window  proc near
  704.           mov ah,6                ;clear window with BIOS routine
  705.           mov al,0                ;specify clear function
  706.           mov cx,030Ah            ;specify window coordinates
  707.           mov dx,0C45h
  708.           mov bh,text_attr            ;attribute to be used
  709.           int 10h
  710.           ret
  711. clear_window  endp
  712. ;
  713. ;------------------------------------------------------------------------------
  714. ;CLEAR_INPUT_LINE clears the window input line.
  715. ;------------------------------------------------------------------------------
  716. clear_input_line proc near
  717.           mov ah,2                ;set cursor to start of input line
  718.           mov dx,020Ah
  719.           mov bh,video_page
  720.           int 10h
  721.           mov ah,10             ;then write a string of spaces
  722.           mov al,32
  723.           mov cx,60
  724.           int 10h
  725.           ret
  726. clear_input_line endp
  727. ;
  728. ;------------------------------------------------------------------------------
  729. ;INITIALIZE prepares the program for residency.
  730. ;------------------------------------------------------------------------------
  731. initialize    proc near
  732. ;
  733. ;Determine what type of video adapter is installed.
  734. ;
  735.           mov ah,12h            ;prepare for call to int 10h
  736.           mov bl,10h            ;function - request EGA info
  737.           int 10h
  738.           cmp bl,10h            ;BL=10h?
  739.           je init1                ;yes, then no EGA installed
  740.           or bh,bh                ;BH=0?
  741.           jne init2             ;no, then it's a monochrome system
  742.           jmp init3
  743. init1:          dec adapter            ;decrement ADAPTER value
  744.           mov ah,15             ;get video mode
  745.           int 10h
  746.           cmp al,7                ;is it mode 7?
  747.           jne init3             ;no, then it's a color system
  748.           dec adapter            ;set ADAPTER to 0
  749. ;
  750. ;Modify video parameter values for monochrome, then initialize the cursor.
  751. ;
  752. init2:          sub video_segment,800h        ;set VIDEO_SEGMENT for monochrome
  753.           mov border_attr,70h        ;change attributes for monochrome
  754.           mov text_attr,07h
  755.           mov default_cursor,0C0Dh        ;set monochrome cursor definition
  756. init3:          call show_cursor            ;set cursor to default mode
  757. ;
  758. ;Determine the port address of the CRT Controller and store it.
  759. ;
  760.           mov ax,40h            ;point ES to BIOS data segment
  761.           mov es,ax
  762.           mov di,63h            ;point DI to address word
  763.           mov dx,es:[di]            ;get CRTC address
  764.           mov addr_6845,dx            ;save it
  765. ;
  766. ;Get and save the address of the DOS BUSY_FLAG.
  767. ;
  768.           mov ah,34h            ;function 34h
  769.           int 21h                ;get address
  770.           mov dos_segment,es        ;save segment
  771.           mov busy_flag,bx            ;save offset
  772. ;
  773. ;Save and replace all required interrupt vectors.
  774. ;
  775.           mov ah,35h            ;get interrupt 9 vector
  776.           mov al,9
  777.           int 21h
  778.           mov old9h,bx            ;save it
  779.           mov old9h[2],es
  780.           mov ah,25h            ;point it to KEYBOARD routine
  781.           lea dx,keyboard
  782.           int 21h
  783.           mov ah,35h            ;get interrupt 1Ch vector
  784.           mov al,1Ch
  785.           int 21h
  786.           mov old1ch,bx            ;save it
  787.           mov old1ch[2],es
  788.           mov ah,25h            ;then point it to TIMER
  789.           lea dx,timer
  790.           int 21h
  791.           mov ah,35h            ;get interrupt 13h vector
  792.           mov al,13h
  793.           int 21h
  794.           mov old13h,bx            ;save it
  795.           mov old13h[2],es
  796.           mov ah,25h            ;point it to BDISK
  797.           lea dx,bdisk
  798.           int 21h
  799.           mov ah,35h            ;get interrupt 28h vector
  800.           mov al,28h
  801.           int 21h
  802.           mov old28h,bx            ;save it
  803.           mov old28h[2],es
  804.           mov ah,25h            ;point it to BACKPROC
  805.           lea dx,backproc
  806.           int 21h
  807. ;
  808. ;Terminate but remain resident in memory.
  809. ;
  810.           mov dx,offset initialize+6216 ;point DX to end of resident code
  811.           int 27h                ;terminate-but-stay-resident
  812. initialize    endp
  813. ;
  814. code          ends
  815.           end begin
  816.