home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol11n15.zip / REDD.ASM < prev    next >
Assembly Source File  |  1992-05-26  |  35KB  |  1,296 lines

  1. ;====================================================================
  2. ;    REDD - Remote Exec Device Driver
  3. ;
  4. ;    Copyright (c) 1992 Douglas Boling
  5. ;====================================================================
  6.         page    66,132
  7. ;--------------------------------------------------------------------
  8. ; BIOS Data segment
  9. ;--------------------------------------------------------------------
  10. bios_data       segment at 40h
  11.             org     17h
  12. shift_state     db      ?                       ;State of shift keys
  13.         org    1Ah
  14. keybuff_head    dw    ?            ;Start ptr for key buff
  15. keybuff_tail    dw    ?             ;End ptr for key buff
  16.  
  17.             org     4Eh
  18. video_buffoff   dw      ?                       ;Offset of video buffer
  19.             org     63h
  20. video_ioregs    dw      ?                       ;I/O addr of video ctlr
  21.         org    80h
  22. keybuff_start    dw    ?            ;Start ptr for keybuff
  23. keybuff_end    dw    ?             ;End ptr for keybuff
  24. video_rows      db      ?                       ;Screen rows
  25. bios_data       ends
  26.         
  27. ;--------------------------------------------------------------------
  28. ; CODE segment
  29. ;--------------------------------------------------------------------
  30.         code    segment    
  31.         assume    cs:code
  32.  
  33. generic_req    struc
  34. Len        db    ?            ;Size of structure
  35. Unit        db    ?
  36. Function    db    ?            ;Requested function 
  37. Status        dw    ?            ;Returned status
  38. Reserved    db    8 dup (?)
  39. generic_req    ends
  40.  
  41. init_req    struc
  42. irLen        db    ?            ;Size of structure
  43. irUnit        db    ?
  44. irFunction    db    ?            ;Requested function 
  45. irStatus    dw    ?            ;Returned status
  46. irReserved    db    8 dup (?)
  47. irUnits        db    ?            ;Number of block drives
  48. irEndAddress    dd    ?            ;End addr of driver
  49. irParmAddress    dd    ?            ;Ptr to cmd line parms
  50. irDriveNumber    db    ?            ;1st drive number
  51. irMessageflag    dw    ?            ;Error word
  52. init_req    ends
  53.  
  54. media_req    struc
  55. mrLen        db    ?            ;Size of structure
  56. mrUnit        db    ?
  57. mrFunction    db    ?            ;Requested function 
  58. mrStatus    dw    ?            ;Returned status
  59. mrReserved    db    8 dup (?)
  60. mrMediaID       db    ?            ;Media descripter
  61. mrReturn        db    ?            ;return value
  62. mrVolumeID    dd    ?            ;Ptr to volumne ID string
  63. media_req    ends
  64.  
  65. buildbpb_req    struc
  66. bbrLen        db    ?            ;Size of structure
  67. bbrUnit        db    ?
  68. bbrFunction    db    ?            ;Requested function 
  69. bbrStatus     dw    ?            ;Returned status
  70. bbrReserved    db    8 dup (?)
  71. bbrMediaID    db    ?            ;Media descripter
  72. bbrFATSector    dd    ?            ;Ptr to 1st FAT sector
  73. bbrBPBAddress    dd    ?            ;Ptr to BPB block
  74. buildbpb_req    ends
  75.  
  76. read_req    struc
  77. rrLen        db    ?            ;Size of structure
  78. rrUnit        db    ?
  79. rrFunction    db    ?            ;Requested function 
  80. rrStatus    dw    ?            ;Returned status
  81. rrReserved    db    8 dup (?)
  82. rrMediaID    db    ?            ;Media descripter
  83. rrBuffer    dd    ?            ;Ptr to data buffer
  84. rrBytesSec    dw    ?            ;Number of sectors to read
  85. rrStartSec    dw    ?            ;Starting sector number
  86. rrVolumeID    dd    ?            ;Ptr to volume ID string
  87. rrHugeStartSec    dd    ?            ;Start sec for >32 Meg drive
  88. read_req    ends
  89.  
  90. ;====================================================================
  91. ;Device driver header
  92. ;====================================================================
  93.         org    0            ;Offset 0 for DD
  94.  
  95. header        dd    -1            ;Ptr to next driver
  96.         dw    0800h            ;Attribute word bits
  97.                         ;15 Character device
  98.                         ;14 IOCTL read/write support
  99.                         ;13 (Char) Output till busy 
  100.                         ;   (Blk) Needs FAT for BPB
  101.                         ;11 Open/Close dev supported
  102.                         ; 7 IOCTL querys supported
  103.                         ; 6 Log drive mapping support
  104.                         ; 4 Fast char input support
  105.                         ; 3 Device is clock device
  106.                         ; 2 Device is NULL device
  107.                         ; 1 (Char) Std out device
  108.                         ;   (Blk) 32 bit sector nums
  109.                         ; 0 Device is Std Input dev
  110.         dw    offset strategy        ;Ptr to strategy routine
  111.         dw    offset interrupt    ;Ptr to interrupt routine
  112.         db    1,0,0,0,0,0,0,0        ;Num of block devices 
  113.  
  114. program        db    10,13,"REDD",10,13
  115.             db      "Copyright (c) 1992 Douglas Boling",13,10
  116.             db      "First published in PC Magazine, September 15, 1992"
  117.             db      13,10,"$",1Ah
  118. ;--------------------------------------------------------------------
  119. ;Boot Sector data for our imaginary drive
  120. ;--------------------------------------------------------------------
  121. boot_sector    =    $
  122.         jmp    short boot_sector_end    ;obligitory jmp instruction
  123.         nop
  124.         db    "IBM x.x  "        ;Stupid IBM tag for DOS 4
  125. BPB_start    =    $
  126. BytesPerSec    dw    200h            ;512 bytes per sector
  127. SecPerCluster    db    1            ;One sec per cluster
  128. ResSectors    dw    1            ;Reserved sectors
  129. NumFATs        db    1            ;Number of File Alloc tables
  130. RootDirEntries    dw    8            ;Num of entries in root dir
  131. Sectors        dw    8            ;Total number of sectors
  132. Media        db    0F0h            ;Media descriptor byte
  133. FATSectors    dw    1            ;Number of sectors per FAT
  134. SecPerTrack    dw    8            ;Num sectors per track
  135. Heads        dw    1            ;Num of heads
  136. HiddenSectors    dd    0            ;Num hidden sectors
  137. HugeSectors    dd    0            ;Num of sec if > 32 Meg 
  138.  
  139. DriveNumber    db    0            ;Used by DOS
  140. Reserved1    db    0            ;Used by DOS
  141. BootSignature    db    29h            ;IDs boot sector format
  142. VolumeID    dd    12345678h        ;Volume ID number
  143. VolumeLabel    db    "REDD       "        ;ASCII volume label
  144. FileSysType    db    "FAT12   "        ;FAT system used
  145. boot_sector_end    =    $
  146. ;
  147. ;Data needed for the driver
  148. ;
  149. req_header_ptr    dd    0            ;Ptr to request header
  150. bpb_array    dw    offset BPB_start    ;Array of BPB pointers
  151. keyname        db    "KEYBOARDIN "        ;Name of keyboard file
  152. volume_name    db    "REDD       ",0        ;ASCIIZ string of vol name
  153.  
  154. cr_flag        db    1            ;Append CR to video LFs 
  155.         even
  156. sys_year    db    0            ;Time needed to set
  157. sys_month    db    0            ;  the time and date for
  158. sys_day        db    0            ;  screen file.
  159. sys_hours    db    0
  160. sys_minutes    db    0
  161. sys_seconds    db    0
  162. timer_low    dw    0            ;Timer ticks since last
  163. timer_high    dw    0            ;  GetSysTime call.
  164. scrtick_low    dw    0            ;Tick count at last screen
  165. scrtick_high    dw    0            ;  write.
  166.  
  167.  
  168. int08_active    dw    -1            ;Interrupt 8 active flag
  169. int08h        dd    -1            ;Old Timer Interrupt 
  170. int10h        dd    -1            ;Old Video Interrupt 
  171. ScreenHead    dd    -1            ;Head of screen buffer queue
  172. ScreenTop    dw    -1            ;Top of screen buffer
  173. ScreenBot    dw    -1            ;End of screen buffer
  174. ScreenTxtSec    dw    2            ;Screen file num of sectors 
  175.  
  176. fileopen_count    dw    0            ;Number of opened files
  177.  
  178. root_update    db    0            ;Indicates change in Root dir
  179. paste_flag    db    0
  180. pastedata_ptr    dw    0
  181. pastedata_end    dw    0
  182. fpclust_size    dw    0
  183. pastecluster    dw    0
  184. pastedirent_ptr    dw    0
  185.  
  186. FATPtr        dw    0            ;Ptr to FAT table
  187. FATSize        dw    0            ;Sectors * 1.5
  188. RootSize    dw    0            ;Root entries * 32
  189. DataPtr        dw    ?            ;Ptr to data sector start
  190.  
  191. jmptable    dw    offset init        ;0  Initialize driver
  192.         dw    offset media_check    ;1  Block device media check
  193.         dw    offset build_bpb    ;2  Build BIOS parameter blk
  194.         dw    offset not_implimented    ;3  I/O control read
  195.         dw    offset read        ;4  Read
  196.         dw    offset not_implimented    ;5  Non-destructive read
  197.         dw    offset not_implimented    ;6  Get input status
  198.         dw    offset not_implimented    ;7  Flush input
  199.         dw    offset write        ;8  Write
  200.         dw    offset write        ;9  Write with verify
  201.         dw    offset not_implimented    ;A  Get output status
  202.         dw    offset not_implimented    ;B  Output flush
  203.         dw    offset not_implimented    ;C  I/O control write
  204.         dw    offset open_device    ;D  Open device
  205.         dw    offset close_device    ;E  Close device
  206.         dw    offset removable_media    ;F  Removable media check
  207.         dw    offset not_implimented    ;10 Output until busy
  208.         dw    offset not_implimented    ;11 Reserved
  209.         dw    offset not_implimented    ;12 Reserved
  210.         dw    offset not_implimented    ;13 Generic I/O control
  211.         dw    offset not_implimented    ;14 Reserved
  212.         dw    offset not_implimented    ;15 Reserved
  213.         dw    offset not_implimented    ;16 Reserved
  214.         dw    offset not_implimented    ;17 Get logic drive mapping
  215.         dw    offset not_implimented    ;18 Set logic drive mapping
  216.         dw    offset not_implimented    ;19 I/O control query
  217. jmptable_end    =    $
  218. max_cmd        equ    (offset jmptable_end - offset jmptable) shr 1
  219. ;====================================================================
  220. ;STRATEGY - Handles strategy calls from DOS by copying the request
  221. ;           header pointer into an internal buffer.
  222. ;====================================================================
  223. strategy    proc    far
  224.         assume    cs:code,ds:nothing,es:nothing
  225.         mov    word ptr cs:[req_header_ptr],bx
  226.         mov    word ptr cs:[req_header_ptr+2],es
  227.         ret
  228. strategy    endp
  229. ;====================================================================
  230. ;INTERRUPT - Handles interrupt calls from DOS by implimenting the
  231. ;            device driver functions
  232. ;====================================================================
  233. interrupt    proc    far
  234.         assume    cs:code,ds:nothing,es:nothing
  235.         push    ax
  236.         push    bx
  237.         push    cx
  238.         push    dx
  239.         push    di
  240.         push    si
  241.         push    bp
  242.         push    ds
  243.         push    es
  244.         pushf
  245.         cld                ;All string operations UP
  246.         mov    di,cs
  247.         mov    ds,di
  248.         assume    ds:code
  249.  
  250.         les    di,req_header_ptr    ;Get ptr to request header
  251.         xor    bx,bx
  252.         mov    bl,es:[di.Function]    ;Get requested function
  253.          cmp    bl,max_cmd
  254.         mov    ax,8003h        ;Load error status
  255.         ja    interrupt_exit
  256.  
  257.         nop
  258.  
  259.  
  260.         shl    bx,1
  261.         call    [bx+jmptable]        ;Call proper routine
  262.         push    ax
  263.         cmp    cs:root_update,0
  264.         je    interrupt_1
  265.            call    check_root
  266. interrupt_1:
  267.         pop    ax
  268.         les    di,req_header_ptr    ;Get ptr to request header
  269.         or    ax,0100h        ;Set done bit
  270. interrupt_exit:
  271.         mov    es:[di.Status],ax    ;Save status in drvr header
  272.         popf
  273.         pop    es
  274.         pop    ds
  275.         pop    bp
  276.         pop    si
  277.         pop    di
  278.         pop    dx
  279.         pop    cx
  280.         pop    bx
  281.         pop    ax
  282.         ret
  283. interrupt    endp
  284.  
  285. ;--------------------------------------------------------------------
  286. ;MEDIA CHECK - Media check function allows DOS to determine if the 
  287. ;              disk type in the drive has changed.
  288. ;Entry: ES:DI - Point to request header structure
  289. ;--------------------------------------------------------------------
  290. media_check    proc    near
  291.         assume    cs:code,ds:code,es:nothing
  292.         mov    es:[di.mrReturn],0    ;Media may have been changed
  293.         mov    word ptr es:[di.rrVolumeID],offset volume_name
  294.         mov    word ptr es:[di.rrVolumeID+2],cs
  295. not_implimented:
  296.         xor    ax,ax            ;Clear return code
  297.         ret
  298. media_check    endp
  299.  
  300. ;--------------------------------------------------------------------
  301. ;BUILD BPB - Build BIOS Parameter Block.
  302. ;Entry: ES:DI - Point to request header structure
  303. ;--------------------------------------------------------------------
  304. build_bpb    proc    near
  305.         assume    cs:code,ds:code,es:nothing
  306.         mov    word ptr es:[di.bbrBPBAddress],offset BPB_start
  307.         mov    word ptr es:[di.bbrBPBAddress+2],cs
  308.         xor    ax,ax
  309.         ret
  310. build_bpb    endp
  311.  
  312. ;--------------------------------------------------------------------
  313. ;READ - Reads sectors from the block device
  314. ;Entry: ES:DI - Point to request header structure
  315. ;--------------------------------------------------------------------
  316. read        proc    near
  317.         assume    cs:code,ds:code,es:nothing
  318.         mov    bx,es:[di.rrStartSec]
  319.         mov    cx,es:[di.rrBytesSec]
  320.         push    cx
  321.         push    di
  322.         push    es
  323.         les    di,es:[di.rrBuffer]
  324.  
  325.  
  326.  
  327.         nop
  328.  
  329.  
  330.  
  331. read_1:
  332.         call    read_sector        ;'Read' a sector
  333.         inc    bx            ;Inc starting sector
  334.         loop    read_1            ;Read again if not done
  335.  
  336.         pop    es            ;Set output fields and term
  337.         pop    di
  338.         pop    cx
  339.         mov    es:[di.rrBytesSec],cx    
  340.         mov    word ptr es:[di.rrVolumeID],offset volume_name
  341.         mov    word ptr es:[di.rrVolumeID+2],cs
  342.         xor    ax,ax
  343.         ret
  344. read        endp
  345.  
  346. ;--------------------------------------------------------------------
  347. ;WRITE - Writes sectors from the block device
  348. ;Entry: ES:DI - Point to request header structure
  349. ;--------------------------------------------------------------------
  350. write        proc    near
  351.         assume    cs:code,ds:code,es:nothing
  352.         mov    bx,es:[di.rrStartSec]
  353.         mov    cx,es:[di.rrBytesSec]
  354.         push    cx
  355.         push    si
  356.         push    ds
  357.         lds    si,es:[di.rrBuffer]
  358.  
  359.  
  360.         nop
  361.  
  362.  
  363.  
  364. write_1:
  365.         call    write_sector        ;'Write' a sector
  366.         inc    bx            ;Inc starting sector
  367.         loop    write_1            ;Read again if not done
  368.  
  369.         pop    ds
  370.         pop    si
  371.         pop    cx
  372.         mov    es:[di.rrBytesSec],cx    
  373.         mov    word ptr es:[di.rrVolumeID],offset volume_name
  374.         mov    word ptr es:[di.rrVolumeID+2],cs
  375.         xor    ax,ax
  376.         ret
  377. write        endp
  378.  
  379. ;--------------------------------------------------------------------
  380. ;OPEN DEVICE - Indicates that a file has been opened on the drive
  381. ;Entry: ES:DI - Point to request header structure
  382. ;--------------------------------------------------------------------
  383. open_device    proc    near
  384.         assume    cs:code,ds:code,es:nothing
  385.         inc    cs:fileopen_count
  386.         xor    ax,ax
  387.         ret
  388. open_device    endp
  389.  
  390. ;--------------------------------------------------------------------
  391. ;CLOSE DEVICE - Indicates that a file has been closed on the drive
  392. ;Entry: ES:DI - Point to request header structure
  393. ;--------------------------------------------------------------------
  394. close_device    proc    near
  395.         assume    cs:code,ds:code,es:nothing
  396.         dec    cs:fileopen_count
  397.         xor    ax,ax
  398.         ret
  399. close_device    endp
  400.  
  401. ;--------------------------------------------------------------------
  402. ;REMOVABLE MEDIA - Informs DOS whether the drive is removable
  403. ;Entry: ES:DI - Point to request header structure
  404. ;--------------------------------------------------------------------
  405. removable_media    proc    near
  406.         assume    cs:code,ds:code,es:nothing
  407.         xor    ax,ax            ;Bit 9 = 0 - drive removable
  408.         ret
  409. removable_media    endp
  410.  
  411. ;--------------------------------------------------------------------
  412. ;READ SECTOR - Simulates a read of a mythical disk sector
  413. ;Entry:    BX - Starting sector
  414. ;       ES:DI - Ptr to data buffer to read data
  415. ;Exit:  ES:DI - Points to byte beyond last data read out to DOS
  416. ;--------------------------------------------------------------------
  417. read_sector    proc    near
  418.         assume    cs:code,ds:code,es:nothing
  419.         push    bx
  420.         push    cx
  421.         cmp    bx,1            ;Check what sector to read
  422.         jb    read_boot
  423.         je    read_FAT
  424.         sub    bx,3
  425.         jb    read_root
  426.  
  427.         cmp    bx,ScreenTxtSec        ;See if reading SCREEN.TXT
  428.         jb    read_screen
  429.  
  430.         call    getdata_ptr        ;Compute buff for sector
  431.         mov    si,bx
  432.         mov    cx,BytesPerSec
  433.         jmp    short read_sector_1
  434. read_screen:
  435.         mov    dx,BytesPerSec
  436.         xchg    bx,dx
  437.         mov    si,word ptr ScreenHead    ;Read this sector as a
  438.         mov    ax,bx            ;  rotating buffer.  The
  439.         mul    dx            ;  ScreenHead ptr points
  440.         add    si,ax            ;  to the start of the
  441.         mov    cx,ScreenBot        ;See if starting past end
  442.         cmp    si,cx            ;  of buffer.
  443.         jb    read_screen_0
  444.         sub    si,cx            ;Yes, wrap ptr to buff start
  445.         add    si,ScreenTop
  446. read_screen_0:
  447.         sub    cx,si            ;Compute len till end of buff
  448.         sub    bx,cx            ;Sub read len from total
  449.         jae    read_screen_1        ;If read len more than total,
  450.         mov    cx,BytesPerSec        ;  change read len to total
  451.         xor    bx,bx            ;Clear total.
  452. read_screen_1:
  453.         rep    movsb            
  454.         mov    si,ScreenTop
  455.         mov    cx,bx
  456.         jcxz    read_sector_exit
  457.         rep    movsb
  458.         jmp    short read_sector_exit
  459. read_boot:
  460.         mov    si,offset boot_sector
  461.         mov    cx,offset boot_sector_end - offset boot_sector
  462.         jmp    short read_sector_1
  463. read_FAT:
  464.         mov    si,FATPtr
  465.         mov    cx,FATSize
  466.         jmp    short read_sector_1
  467. read_root:
  468.         mov    si,offset root_dir
  469.         call    set_time        ;Set time for screen file
  470.         mov    cx,RootSize
  471. read_sector_1:
  472.         mov    dx,BytesPerSec        ;Copy data
  473.         sub    dx,cx            ;See how much is left for
  474.         rep    movsb            ;  a complete sector
  475.         xor    al,al
  476.         mov    cx,dx            ;Fill in remainder of 
  477.         jcxz    read_sector_exit    ;  sector with zeros.
  478.         rep    stosb
  479. read_sector_exit:
  480.         pop    cx
  481.         pop    bx
  482.         ret
  483. read_sector    endp
  484.  
  485. ;--------------------------------------------------------------------
  486. ;WRITE SECTOR - Simulates a write of a mythical disk sector
  487. ;Entry:    BX - Starting sector
  488. ;       DS:SI - Ptr to data buffer 
  489. ;Exit:  DS:SI - Points to byte beyond last data read into drive
  490. ;--------------------------------------------------------------------
  491. write_sector    proc    near
  492.         assume    cs:code,ds:nothing,es:nothing
  493.         push    bx
  494.         push    cx
  495.         push    di
  496.         push    es
  497.         mov    ax,cs
  498.         mov    es,ax
  499.         assume    es:code
  500.  
  501.         cmp    bx,1            ;Check what sector to write
  502.         jb    write_boot
  503.         je    write_FAT
  504.         sub    bx,3
  505.         jb    write_root
  506.  
  507.         call    getdata_ptr        ;Compute buff for sector
  508.         mov    di,bx
  509.         mov    cx,BytesPerSec
  510.         jmp    short write_sector_1
  511. write_boot:
  512.         mov    di,offset boot_sector
  513.         mov    cx,offset boot_sector_end - offset boot_sector
  514.         jmp    short write_sector_1
  515. write_FAT:
  516.         mov    di,cs:FATPtr
  517.         mov    cx,cs:FATSize
  518.         jmp    short write_sector_1
  519. write_root:
  520.         mov    di,offset root_dir
  521.         mov    cx,cs:RootSize
  522.         inc    cs:root_update
  523. write_sector_1:
  524.         rep    movsb
  525. write_sector_exit:
  526.         pop    es
  527.         pop    di
  528.         pop    cx
  529.         pop    bx
  530.         ret
  531. write_sector    endp
  532.  
  533. ;--------------------------------------------------------------------
  534. ;GETDATA PTR - Returns the offet in RAM for a given data sector
  535. ;Entry: BX - Cluster - 2
  536. ;Exit:  BX - Ptr to data
  537. ;--------------------------------------------------------------------
  538. getdata_ptr    proc    near
  539.         assume    cs:code,ds:nothing,es:nothing
  540.         push    ax
  541.         push    dx
  542.         mov    ax,bx            ;Copy starting data sec
  543.         mul    cs:BytesPerSec        ;Mul by size of data sec
  544.         mov    bx,ax            ;Add starting offset of
  545.         add    bx,cs:DataPtr        ;  data buffer.
  546.         pop    dx
  547.         pop    ax
  548.         ret
  549. getdata_ptr    endp
  550.  
  551. ;--------------------------------------------------------------------
  552. ;CHECK ROOT - Checks changes in the root directory 
  553. ;--------------------------------------------------------------------
  554. check_root    proc    near
  555.         assume    cs:code,ds:nothing,es:nothing
  556.         push    ds
  557.         push    es
  558.         mov    ax,cs
  559.         mov    ds,ax
  560.         mov    es,ax
  561.         assume    cs:code,ds:code,es:code
  562.         mov    root_update,0        ;Clear flag
  563.         cmp    paste_flag,0        ;Don't bother if we are        
  564.         jne    check_root_exit        ;  already pasting.
  565.         mov    si,offset root_dir
  566.         mov    cx,RootDirEntries    
  567.         mov    di,offset keyname
  568. check_root_1:
  569.         push    cx            ;Scan through root looking
  570.         push    si            ;  for the name of the
  571.         push    di            ;  keyboard file.  
  572.         mov    cx,11
  573.         repe    cmpsb
  574.         pop    di
  575.         pop    si
  576.         pop    cx
  577.         je    check_root_2
  578.         add    si,32
  579.         loop    check_root_1
  580.         jmp    short check_root_exit
  581. check_root_2:
  582.         xor    bx,bx
  583.         or    bx,[si+1ah]        ;See if starting cluster set
  584.         je    check_root_exit
  585.         mov    cx,word ptr [si+1ch]    ;Get file size
  586.         or    cx,cx
  587.         je    check_root_exit        ;If 0, exit
  588.         mov    ax,cx
  589.         xor    dx,dx
  590.         div    BytesPerSec        ;Compute number of sectors
  591.         mov    fpclust_size,dx        ;  and size of last sector.
  592.         mov    pastedirent_ptr,si
  593.         mov    pastecluster,bx
  594.         call    next_pasteclust        ;Compute pointers to sector
  595.         mov    paste_flag,1        ;Allow paste
  596. check_root_exit:
  597.         pop    es
  598.         pop    ds
  599.         ret
  600. check_root    endp
  601.  
  602. ;-------------------------------------------------------------------------
  603. ;DELETE FILE - Deletes a file from the driver disk
  604. ;Entry: SI - Pointer to directory entry for file
  605. ;-------------------------------------------------------------------------
  606. delete_file    proc    near
  607.         assume    cs:code,ds:code,es:nothing
  608.         push    cx
  609.         xor    ax,ax
  610.         mov    bx,[si+1ah]        ;Get starting cluster
  611. delete_file_1:
  612.         mov    cx,bx
  613.         call    get_fat_entry
  614.         xchg    bx,cx
  615.         call    set_fat_entry        ;Zero entry
  616.         mov    bx,cx
  617.         cmp    bx,0fffh        ;See if last entry
  618.               jne    delete_file_1
  619.  
  620.         mov    byte ptr [si],0e5h    ;Clear name
  621.         pop    cx
  622.         ret
  623. delete_file    endp
  624.  
  625. ;-------------------------------------------------------------------------
  626. ; GET FAT ENTRY - Returns the contents of a 12 bit FAT entry
  627. ; Entry:    BX - Entry into FAT table
  628. ; Exit:     BX - Next entry
  629. ;-------------------------------------------------------------------------
  630. get_fat_entry    proc    near
  631.         assume    cs:code,ds:code,es:nothing
  632.         push    ax
  633.         push    di
  634.  
  635.         mov    di,FATPtr
  636.         add    di,bx
  637.             shr     bx,1                    ;12 bit FAT
  638.             mov     ax,ds:[bx+di]
  639.             jnc     get_fat_entry_2
  640.             shr     ax,1
  641.             shr     ax,1
  642.             shr     ax,1
  643.             shr     ax,1
  644. get_fat_entry_2:
  645.             and     ah,0fh                  ;Clear top nibble
  646. get_fat_entry_3:
  647.         mov    bx,ax            ;Copy entry data
  648.         pop     di
  649.         pop    ax
  650.         ret
  651. get_fat_entry     endp
  652.  
  653. ;-------------------------------------------------------------------------
  654. ; SET FAT ENTRY - Writes a 12 bit FAT table entry 
  655. ; Entry:    BX - Pointer to fat table entry
  656. ;           AX - Data to write to FAT table
  657. ;-------------------------------------------------------------------------
  658. set_fat_entry    proc    near
  659.         assume    cs:code,ds:code,es:nothing
  660.         push    ax
  661.         push    bx
  662.         push    di
  663.  
  664.         mov    di,FATPtr
  665.         add    di,bx
  666.             shr     bx,1                    ;12 bit FAT
  667.         pushf
  668.         add    di,bx
  669.         popf
  670.         mov    bx,ds:[di]        ;Get data
  671.         jc    set_fat_1        ;Jump if odd
  672.         and    bx,0f000h        ;Remove old data
  673.         jmp    short set_fat_2
  674. set_fat_1:
  675.         and    bx,000fh        ;Remove old data
  676.         shl    ax,1
  677.         shl    ax,1
  678.         shl    ax,1
  679.         shl    ax,1
  680. set_fat_2:
  681.         or    ax,bx
  682.         mov    ds:[di],ax        ;Write data
  683.         pop    di
  684.         pop    bx
  685.         pop    ax
  686.         ret
  687. set_fat_entry    endp
  688.  
  689. ;====================================================================
  690. ;TIMER INT - Interrupt 8h timer hook.  This routine keeps the time
  691. ;            and, when necessary, pastes data into the keyboard buff
  692. ;====================================================================
  693. timerint    proc    far
  694.         assume    cs:code,ds:nothing,es:nothing
  695.         pushf
  696.         add    word ptr cs:timer_low,1
  697.         adc    word ptr cs:timer_high,0
  698.         cmp    cs:paste_flag,0
  699.         jne    timerint_1
  700. timerint_exit:    
  701.         popf
  702.         jmp    cs:[int08h]        ;Jmp to old interrupt
  703. timerint_1:
  704.         inc    cs:int08_active
  705.         jne    timerint_exit2
  706.         push    ax
  707.         push    ds
  708.                mov    ax,cs
  709.         mov    ds,ax
  710.         assume    ds:code
  711. timerint_2:
  712.         call    push_key
  713.         jc    timerint_exit1
  714.         cmp    paste_flag,0
  715.         jne    timerint_2
  716. timerint_exit1:
  717.         pop    ds
  718.         pop    ax
  719. timerint_exit2:
  720.         dec    cs:int08_active
  721.         jmp    short timerint_exit
  722. timerint    endp
  723.  
  724. ;-----------------------------------------------------------------------------
  725. ; PUSH KEY  Fills the keyboard buffer with data 
  726. ; Exit: CF - Set if keyboard buffer full
  727. ;       AX - modified
  728. ;-----------------------------------------------------------------------------
  729. push_key    proc    near
  730.         assume    ds:nothing,es:nothing
  731.         push    bx
  732.         push    di
  733.         push    si
  734.         push    es
  735.         cld                ;String moves UP
  736.         mov    ax,bios_data
  737.         mov    es,ax
  738.         assume    es:bios_data
  739.         cli                ;No interrupts
  740.         mov    di,es:[keybuff_tail]
  741.         push    di
  742.         call     inckeyptr
  743.         cmp    di,es:[keybuff_head]    ;See if buffer full
  744.         pop    di
  745.         stc
  746.         je    push_key_exit
  747.  
  748.         mov    si,pastedata_ptr
  749.         lodsb                ;Get character to paste
  750.         cmp    si,pastedata_end
  751.         jb    push_key_3
  752.         push    ax
  753.         mov    bx,pastecluster        ;See if cluster is the last
  754.         call    get_fat_entry        
  755.         cmp    bx,0fffh
  756.         je    push_key_1
  757.         mov    pastecluster,bx
  758.         call    next_pasteclust        ;Compute ptrs for next sector
  759.         jmp    short push_key_2
  760. push_key_1:
  761.         mov    paste_flag,0        ;Disable paste
  762.         mov    si,pastedirent_ptr    ;Delete paste file
  763.         call    delete_file
  764. push_key_2:
  765.         pop    ax
  766. push_key_3:
  767.         mov    pastedata_ptr,si
  768.         or    al,al            ;Don't stuff null char
  769.         je    push_key_5
  770.         jns    push_key_31
  771.         and    ax,007fh        ;Remove sign bit, clear AH
  772.         xchg    ah,al            ;Place char in scan code 
  773.         jmp    short push_key_4
  774. push_key_31:
  775.         cmp    al,0ah            ;Don't stuff line feeds
  776.         je    push_key_5
  777.         cmp    al,1ah            ;Don't stuff End Of File char
  778.         je    push_key_5
  779.           xor    ah,ah            ;Clear scan code
  780.         cmp    al,0dh            ;If CR character, add proper
  781.         jne    push_key_4        ;  scan code for Word Perfect
  782.         mov    ah,1ch
  783. push_key_4:        
  784.         mov      es:[di],ax        ;Don't use STOSW, ptr must
  785.         call    inckeyptr        ;  be updated by inckeyptr
  786.         mov    es:[keybuff_tail],di    ;Save keybuff ptr
  787. push_key_5:
  788.         clc
  789. push_key_exit:
  790.         pop    es
  791.         pop    si
  792.         pop    di
  793.         pop    bx
  794.         ret
  795. push_key    endp
  796.  
  797. ;--------------------------------------------------------------------
  798. ;NEXT PASTECLUST - Sets the paste variables for a sector
  799. ;Entry: BX - new sector
  800. ;--------------------------------------------------------------------
  801. next_pasteclust    proc    near
  802.         push    dx
  803.         push    bx
  804.         call    get_fat_entry        
  805.         mov    dx,BytesPerSec
  806.         cmp    bx,0fffh
  807.         jne    next_pc_1
  808.         mov    dx,fpclust_size
  809. next_pc_1:
  810.         pop    bx
  811.         sub    bx,2
  812.         call    getdata_ptr
  813.         mov    pastedata_ptr,bx
  814.         add    bx,dx
  815.         mov    pastedata_end,bx
  816.         pop    dx
  817.         ret
  818. next_pasteclust    endp
  819.  
  820. ;-----------------------------------------------------------------------------
  821. ; INCKEYPTR Incriments the keyboard buffer pointer
  822. ; Entry: DI - Current Keyboard tail pointer
  823. ;-----------------------------------------------------------------------------
  824. inckeyptr    proc    near
  825.         assume    es:bios_data
  826.         inc    di            ;Make room in buffer
  827.         inc    di
  828.         cmp    di,es:[keybuff_end]    ;Get ptr to end of buffer
  829.         jne    inckeyptr_1
  830.         mov    di,es:[keybuff_start]    ;Get ptr to buffer offset
  831. inckeyptr_1:
  832.         ret
  833. inckeyptr    endp
  834.  
  835. ;====================================================================
  836. ;VID INT - Interrupt 10h video hook.  This routine monitors and 
  837. ;          records any BIOS writes to the screen into the 'file'
  838. ;          SCREEN.TXT.
  839. ;====================================================================
  840. vidint        proc    far
  841.         assume    cs:code,ds:nothing,es:nothing
  842.         cmp    ah,9
  843.         jae    vidint_1
  844. vidint_exit:        
  845.         jmp    cs:[int10h]        ;Jmp to old interrupt
  846. vidint_1:
  847.         push    cx
  848.         push    di
  849.         push    es
  850.  
  851.         cmp    ah,09h
  852.         je    vidint_wrtchr1
  853.         cmp    ah,0ah
  854.         je    vidint_wrtchr1
  855.         cmp    ah,0eh       
  856.         je    vidint_wrtchr
  857.         cmp    ah,13h
  858.         jne    vidint_exit1
  859.         push    ax
  860.         push    si
  861.         push    ds
  862.         mov    si,es
  863.         mov    ds,si
  864.         mov    si,bp            ;Copy ptr to string
  865.  
  866.         les    di,cs:ScreenHead    ;Get ptr to buffer
  867.         mov    ah,al
  868. vidint_2:
  869.         jcxz    vidint_4
  870.         lodsb                ;Read character
  871.         call    save_char        ;Store character
  872.         cmp    ah,2
  873.         jb    vidint_3
  874.         inc    si            ;Skip past attribute
  875. vidint_3:
  876.         loop    vidint_2
  877. vidint_4:
  878.         pop    ds
  879.         pop    si
  880.         pop    ax
  881.         jmp    short vidint_5
  882. vidint_wrtchr:
  883.         mov    cx,1
  884. vidint_wrtchr1:
  885.         les    di,cs:ScreenHead    ;Get ptr to buffer
  886.         jcxz    vidint_5
  887.         call    save_char        ;Save character
  888.         loop    vidint_wrtchr1
  889. vidint_5:
  890.         mov    word ptr cs:ScreenHead,di
  891.         pushf
  892.         cli
  893.         mov    di,cs:timer_low        ;Mark last time screen
  894.         mov    cx,cs:timer_high    ;  updated.
  895.         mov    cs:scrtick_low,di
  896.         mov    cs:scrtick_high,cx
  897.         popf
  898. vidint_exit1:
  899.         pop    es
  900.         pop    di
  901.         pop    cx
  902.         jmp    vidint_exit
  903. vidint        endp
  904.  
  905. ;--------------------------------------------------------------------
  906. ;SAVE CHAR - Saves a character into the SCREEN.TXT file
  907. ;--------------------------------------------------------------------
  908. save_char    proc    near
  909.         assume    cs:code,ds:nothing,es:code
  910.         cmp    al,13            ;See if CR
  911.         je    save_char_2
  912.         cmp    al,10
  913.         je    save_char_3
  914. save_char_0:
  915.         stosb
  916. save_char_01:
  917.         cmp    di,cs:ScreenBot
  918.         jae    save_char_1
  919.         ret
  920. save_char_1:
  921.         mov    di,cs:ScreenTop
  922.         ret
  923. save_char_2:
  924.         mov    cs:cr_flag,0
  925.         jmp    short save_char_0
  926. save_char_3:
  927.         cmp    cs:cr_flag,0
  928.         je    save_char_0
  929.         stosb
  930.         mov    al,13
  931.         stosb
  932.         mov    al,10
  933.         jmp    short save_char_01
  934.         ret
  935. save_char    endp
  936.  
  937. ;--------------------------------------------------------------------
  938. ;INIT TIMER - Calls the BIOS to retrieve the system time
  939. ;--------------------------------------------------------------------
  940. init_timer    proc    near
  941.         assume    cs:code,ds:code,es:nothing
  942.         push    bx
  943.         mov    ah,2            ;Get system time
  944.         int    1ah
  945.         mov    al,ch
  946.         call    un_bcd
  947.         mov    sys_hours,al
  948.         mov    al,cl
  949.         call    un_bcd
  950.         mov    sys_minutes,al
  951.         mov    al,dh
  952.         call    un_bcd
  953.         mov    sys_seconds,al
  954.         mov    ah,4            ;Get system time
  955.         int    1ah
  956.         mov    al,cl
  957.         call    un_bcd
  958.         xor    ah,ah
  959.         cmp    ch,19            ;See if next century
  960.         je    init_timer_1
  961.         add    ax,100
  962. init_timer_1:
  963.         sub    ax,80            ;Convert to relative date
  964.         mov    sys_year,al
  965.         mov    al,dh
  966.         call    un_bcd
  967.         mov    sys_month,al
  968.         mov    al,dl
  969.         call    un_bcd
  970.         mov    sys_day,al
  971.         pushf
  972.         cli
  973.         mov    timer_low,0
  974.         mov    timer_high,0
  975.         popf
  976.         pop    bx
  977.         ret
  978. init_timer    endp
  979.  
  980. ;--------------------------------------------------------------------
  981. ;SET TIME - Sets the time of file in the directory
  982. ;Entry: SI - Pointer to the directory entry
  983. ;--------------------------------------------------------------------
  984. set_time    proc    near
  985.         assume    cs:code,ds:code,es:nothing
  986.         mov     ax,scrtick_low
  987.         mov    dx,scrtick_high
  988.         call    compute_elapsed
  989.  
  990.         add    al,sys_seconds
  991.         cmp    al,60
  992.         jb    set_time_1
  993.         inc    cl
  994.         sub    al,60
  995. set_time_1:
  996.         add    cl,sys_minutes
  997.         cmp    cl,60
  998.         jb    set_time_2
  999.         inc    ch
  1000.         sub    cl,60
  1001. set_time_2:
  1002.         add    ch,sys_hours
  1003.         cmp    ch,24
  1004.         jb    set_time_3
  1005.         inc    dh
  1006.         sub    ch,24
  1007. set_time_3:
  1008.         shr    al,1            ;Divide seconds by 2
  1009.         and    ax,1fh
  1010.         mov    bh,cl            ;Get minutes
  1011.         and    bx,3f00h
  1012.         shr    bx,1
  1013.         shr    bx,1
  1014.         shr    bx,1
  1015.         or    ax,bx
  1016.         mov    bh,ch            ;Get hours
  1017.         shl    bx,1
  1018.         shl    bx,1
  1019.         shl    bx,1
  1020.         and    bx,0f800h
  1021.         or    ax,bx
  1022.         mov    [si+16h],ax        ;Save time in dir entry
  1023.         mov    al,sys_day
  1024.         mov    cl,sys_month
  1025.         mov    ch,sys_year
  1026.         or    dh,dh
  1027.         je    set_time_4
  1028.         call    inc_date        ;Inc to next day
  1029. set_time_4:
  1030.         and    ax,3fh
  1031.         shl    cl,1
  1032.         shl    cl,1
  1033.         shl    cl,1
  1034.         shl    cl,1
  1035.         shl    cx,1
  1036.         or    ax,cx
  1037.         mov    [si+18h],ax        ;Save date in dir entry
  1038.         ret
  1039. set_time    endp
  1040.  
  1041. ;--------------------------------------------------------------------
  1042. ;COMPUTE ELAPSED - Computes the elapsed time from a 32 bit timer tick 
  1043. ;                  count.
  1044. ;Entry: AX,DX - Timer tick count
  1045. ;Exit:     DH - Days
  1046. ;          CH - Hours
  1047. ;          CL - Minutes
  1048. ;          DL - Seconds
  1049. ;--------------------------------------------------------------------
  1050. compute_elapsed    proc    near
  1051.         assume    cs:code,ds:code,es:nothing
  1052.         push    bx
  1053.         push    di
  1054.         xor    bx,bx
  1055.         mov    ch,dl            ;Save hours
  1056.         cmp    dl,24            ;If longer than 24 hours,
  1057.         jb    compute_1        ;  compute days.
  1058.         push    ax
  1059.         xor    ax,ax
  1060.         xchg    ax,dx
  1061.         mov    di,24
  1062.         div    di
  1063.         mov    bl,al            ;Save days
  1064.         mov    dx,ax
  1065.         mul    di
  1066.         mov    ch,al
  1067.         pop    ax
  1068. compute_1:
  1069.         xor    dx,dx
  1070.         mov    di,1092            ;Ticks per minute
  1071.         div    di
  1072.         mov    cl,al            ;Save minutes
  1073.         xor    ax,ax
  1074.         xchg    ax,dx
  1075.         mov    di,10
  1076.         mul    di
  1077.         mov    di,182
  1078.         div    di
  1079.         mov    dl,al
  1080.         mov    di,ax
  1081.         mov    dh,bl
  1082.         pop    di
  1083.         pop    bx
  1084.         ret
  1085. compute_elapsed    endp
  1086.  
  1087. ;--------------------------------------------------------------------
  1088. ;INC DATE - Propigates a incrimented date though the month and year.
  1089. ;Entry: AL - Day
  1090. ;       CL - Month
  1091. ;       CH - Years since 1980
  1092. ;--------------------------------------------------------------------
  1093. inc_date    proc    near
  1094.         inc    al            ;Incriment date
  1095.         push    bx
  1096.         mov    bx,1f1eh        ;bh=31,bl=30
  1097.         cmp    cl,7            ;Up till Aug. odd numbered
  1098.         jbe    inc_date_1        ;  months have 31 days.  
  1099.         xchg    bl,bh            ;  After, even months have 31
  1100. inc_date_1:
  1101.         test    cl,1            ;See if odd month
  1102.         je    inc_date_2        ;No, branch
  1103.         xchg    bl,bh
  1104. inc_date_2:
  1105.         cmp    cl,2            ;See if Feb
  1106.         jne    inc_date_3
  1107.         mov    bl,28
  1108.         test    ch,3            ;Leap year if 4 year multiple
  1109.         jne    inc_date_3        ;  of 1980. Fails at 2100
  1110.         mov    bl,29            ;  since 2100 not a leap year
  1111. inc_date_3:
  1112.         cmp    al,bl
  1113.         jbe    inc_date_exit
  1114.         mov    al,1            ;Set to 1st day of the month
  1115.         inc    cl            ;Inc month
  1116.         cmp    cl,13            ;See if end of year
  1117.         jne    inc_date_exit
  1118.         mov    cl,1            ;Set to Jan.
  1119.         inc    ch            ;Inc year
  1120. inc_date_exit:
  1121.         pop    bx
  1122.         ret
  1123. inc_date    endp
  1124.  
  1125. ;--------------------------------------------------------------------
  1126. ;UN BCD - Returns a binary number for one coded in BCD
  1127. ;Entry: AL - BCD number
  1128. ;Exit:  AL - Binary number
  1129. ;--------------------------------------------------------------------
  1130. un_bcd        proc    near
  1131.         assume    cs:code,ds:nothing,es:nothing
  1132.         push    bx
  1133.         mov    bl,al
  1134.         shr    al,1
  1135.         shr    al,1
  1136.         shr    al,1
  1137.         shr    al,1
  1138.         mov    ah,10
  1139.         mul    ah
  1140.         and    bl,0fh
  1141.         add    al,bl
  1142.         pop    bx
  1143.         ret
  1144. un_bcd        endp
  1145. ;--------------------------------------------------------------------
  1146. ;FINAL INSTALL - Initializes the data structures needed for the drive
  1147. ;Entry: ES:DI - Point to request header structure
  1148. ;          DX - Size of data sectors
  1149. ;--------------------------------------------------------------------
  1150. final_install    proc    near
  1151.         assume    cs:code,ds:code,es:nothing
  1152.         mov    di,cs
  1153.         mov    es,di
  1154.         assume    es:code
  1155.  
  1156.         mov    di,offset root_dir + 64
  1157.         mov    cx,RootSize
  1158.         sub    cx,64
  1159.         xor    ax,ax
  1160.         rep    stosb
  1161.  
  1162.         mov    di,FATPtr
  1163.         mov    al,Media        ;Initialize FAT
  1164.         stosb                ;First FAT bytes contain
  1165.         mov    ax,-1            ;  media descriptor byte 
  1166.         stosw                ;  followed by FF FF.
  1167.  
  1168.         mov    cx,ScreenTxtSec
  1169.         mov    bx,screen_start
  1170. final_install_0:
  1171.         dec    cx
  1172.         jcxz    final_install_01
  1173.         mov    ax,bx
  1174.         inc    ax
  1175.         call    set_fat_entry
  1176.         mov    bx,ax
  1177.         jmp    short final_install_0
  1178. final_install_01:
  1179.         mov    ax,-1
  1180.         call    set_fat_entry
  1181. final_install_02:
  1182.         inc    bx
  1183.         cmp    bx,Sectors
  1184.         ja    final_install_3
  1185.         xor    ax,ax
  1186.         call    set_fat_entry
  1187.         jmp    short final_install_02
  1188. final_install_3:
  1189.         mov    di,DataPtr
  1190.         mov    cx,dx                 ;Fill 1st data sector for
  1191.         mov    al,' '            ;  SCREEN.TXT file.  Might
  1192.         rep    stosb            ;  as well init the rest.
  1193.  
  1194.         mov    ax,3510h        ;Get video interrupt vector
  1195.         int    21h
  1196.         mov    word ptr [int10h],bx
  1197.         mov    word ptr [int10h+2],es
  1198.         mov    ax,2510h        ;Set to our handler
  1199.         mov    dx,offset vidint
  1200.         int    21h
  1201.         mov    ax,3508h        ;Get timer interrupt vector
  1202.         int    21h
  1203.         mov    word ptr [int08h],bx
  1204.         mov    word ptr [int08h+2],es
  1205.         mov    ax,2508h        ;Set to our handler
  1206.         mov    dx,offset timerint
  1207.         int    21h
  1208.         xor    ax,ax            ;Clear return code
  1209.         ret
  1210. final_install    endp
  1211.         even                ;Keep things on even addrs
  1212. ;
  1213. ;Start root directory with entry for screen.txt
  1214. ;
  1215. root_dir    db    "SCREEN  OUT"        ;Name
  1216.         db    1            ;Attribute (Read only)
  1217.         db    10 dup (0)        ;Reserved
  1218. screen_time    dw    0            ;Time of file
  1219. screen_date    dw    0            ;Date of file
  1220. screen_start    dw    2            ;Starting cluster
  1221. screen_size    dd    0            ;Size of file 
  1222. volumne_entry    db    "REDD       "        ;Name
  1223.         db    8            ;Attribute (Volume)
  1224.         db    10 dup (0)        ;Reserved
  1225.         dw    0            ;Time of file
  1226.         dw    0            ;Date of file
  1227.         dw    0            ;Starting cluster
  1228.         dd    0            ;Size of file 
  1229.  
  1230. end_of_resident    =    $
  1231. ;--------------------------------------------------------------------
  1232. ;Non-resident data
  1233. ;--------------------------------------------------------------------
  1234. initmsg        db    13,10,"REDD installed as drive "
  1235. initdrv        db    " :",13,10,10,'$'
  1236.  
  1237. ;--------------------------------------------------------------------
  1238. ;INIT - Initializes the device driver
  1239. ;Entry: ES:DI - Point to request header structure
  1240. ;--------------------------------------------------------------------
  1241. init        proc    near
  1242.         assume    cs:code,ds:code,es:nothing
  1243.         mov    ah,9            ;Print copyright
  1244.         mov    dx,offset program
  1245.         int    21h
  1246.         call    init_timer        ;Init driver clock
  1247.  
  1248.         mov    bx,offset root_dir
  1249.         mov    ax,32            ;Compute size of root dir
  1250.         mov    dx,RootDirEntries    
  1251.         mul    dx
  1252.         mov    RootSize,ax
  1253.  
  1254.         add    bx,ax
  1255.         mov    FATPtr,bx
  1256.         mov    ax,Sectors
  1257.         mov    dx,ax            ;Mul sectors by 1.5
  1258.         shr    ax,1
  1259.         adc    ax,dx
  1260.         mov    FATSize,ax
  1261.         add    bx,ax
  1262.  
  1263.         mov    DataPtr,bx
  1264.         mov    word ptr ScreenHead,bx     ;Init screen buffer ptrs to
  1265.         mov    word ptr ScreenHead+2,cs ;  1st data sector.
  1266.         mov    ScreenTop,bx           
  1267.         mov    ax,ScreenTxtSec
  1268.         mul    BytesPerSec
  1269.         mov    word ptr screen_size,ax
  1270.         add    ax,bx
  1271.         mov    ScreenBot,ax
  1272.  
  1273.         mov    ax,Sectors        ;Compute size of data
  1274.         mul    BytesPerSec        ;  sectors.
  1275.         mov    dx,ax            ;Save data sector size
  1276.         add    ax,bx
  1277.  
  1278.         les    di,req_header_ptr     ;Get ptr to request header
  1279.         mov    cl,es:[di.irDriveNumber] ;  the drive number being
  1280.         add    cl,'A'             ;  used.
  1281.         mov    initdrv,cl
  1282.         mov    word ptr es:[di.irEndAddress],ax    ;Set memory
  1283.         mov    word ptr es:[di.irEndAddress+2],cs    ;  size
  1284.         mov    word ptr es:[di.irParmAddress],offset BPB_array
  1285.         mov    word ptr es:[di.irParmAddress+2],cs
  1286.         mov    word ptr es:[di.irUnits],1
  1287.         push    dx
  1288.         mov    ah,9             ;Print message indicating
  1289.         mov    dx,offset initmsg    ;  disk letter.
  1290.         int    21h
  1291.         pop    dx
  1292.         jmp    final_install
  1293. init        endp
  1294. code        ends
  1295.         end
  1296.