home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progasm / mbootasm.arj / MBOOT.ASM
Encoding:
Assembly Source File  |  1991-02-20  |  169.9 KB  |  5,243 lines

  1.               PAGE    ,132
  2. ;============================================================================
  3. ; MultiBoot - A program to allow PC Compatibles to have multiple
  4. ;             boot sequences.
  5. ;
  6. ;  Release history:
  7. ;            
  8. ;            1.0        Initial Release     PC Magazine Vol. 10, Num 4
  9. ;            1.1        Fixed bug in Session add code.
  10. ;                       Added better error messages to Install routine.
  11. ;
  12. ;============================================================================
  13. ROOT_DIR        equ     2400h            ;Offset in of root dir
  14.  
  15. DATA_SEG1       equ     1790h            ;Holds IO.SYS data on copy
  16. DATA_SEG2       equ     2790h            ;Holds MSDOS.SYS data on copy
  17. FAT_SEGMENT1    equ     3790h            ;Holds 1st 64K of FAT
  18. FAT_SEGMENT2    equ     4790h            ;Holds 2nd 64K of FAT
  19.  
  20. NAME_LENGTH     equ     20            ;Length of session name 
  21. DTA_OFFSET    equ    80h
  22. SYSFILE_ATTR    equ    07h            ;Hidden, system, read only.
  23.  
  24. NEXT_ENTRY      equ     offset name2 - offset name1
  25. AUTO_OFFSET     equ     offset auto1 - offset name1
  26. CONFIG_OFFSET   equ     offset config1 - offset name1
  27. OSTYPE_OFFSET   equ     offset ostype1 - offset name1
  28.  
  29. NEXT_OSENTRY    equ     offset os_name2 - offset opsys_table
  30. OPSYS_TYPE      equ     offset os_boottype - offset opsys_table
  31.  
  32. MENU_SELECTED   equ     offset selected - offset menu_struc
  33. MENU_PROMPT     equ     offset prompt_loc - offset menu_struc
  34. MENU_TIMEOUT    equ     offset timeout - offset menu_struc
  35. MENU_FIRSTITEM  equ     offset firstitem - offset menu_struc
  36.  
  37. COLOR_NORM      equ     17h            ;Video attributes used for
  38. COLOR_HIGH      equ     71h            ;  menus.
  39. BW_NORM          equ     07h
  40. BW_HIGH          equ     70h
  41.  
  42. partition_ptrl  equ     word ptr [bp-60]
  43. partition_ptrh  equ     word ptr [bp-58]
  44. boot_disk       equ     byte ptr [bp-56]
  45. sectors2read    equ     byte ptr [bp-55]
  46. fat_sectorl     equ     word ptr [bp-54]
  47. fat_sectorh     equ     word ptr [bp-52]
  48. root_sectorl    equ     word ptr [bp-50]
  49. root_sectorh    equ     word ptr [bp-48]
  50. root_bytes      equ     word ptr [bp-46]
  51. data_startl     equ     word ptr [bp-44]
  52. data_starth     equ     word ptr [bp-42]
  53. read_buff       equ     word ptr [bp-36]
  54. old_choice      equ     word ptr [bp-34]
  55. bytes_per_clust equ     word ptr [bp-30]
  56. new_io_size    equ    word ptr [bp-24]
  57. new_dos_size    equ    word ptr [bp-22]
  58. low_fat_size    equ    word ptr [bp-20]
  59. hi_fat_size    equ    word ptr [bp-18]
  60.  
  61. bytes_per_sec   equ     word ptr [bp+0bh]
  62. sec_per_cluster equ     byte ptr [bp+0dh]
  63. reserved_sec    equ     word ptr [bp+0eh]
  64. number_of_fats  equ     byte ptr [bp+10h]
  65. root_size       equ     word ptr [bp+11h]
  66. total_sec       equ     word ptr [bp+13h]
  67. media_des_byte  equ     byte ptr [bp+15h]
  68. sec_per_fat     equ     word ptr [bp+16h]
  69. sec_per_track   equ     word ptr [bp+18h]
  70. number_of_heads equ     word ptr [bp+1ah]
  71. num_hidden_sec  equ     word ptr [bp+1ch]
  72. total_sec_long  equ     word ptr [bp+20h]
  73. drive_number       equ     word ptr [bp+24h]
  74. reserved        equ     word ptr [bp+25h]
  75. extended_flag   equ     word ptr [bp+26h]
  76. vol_serial      equ     word ptr [bp+27h]
  77. vol_name        equ     word ptr [bp+2bh]
  78.  
  79. ;============================================================================
  80. ; MBOOT - A substitute boot record to allow PC Compatibles to have
  81. ;           multiple boot sequences.
  82. ;
  83. ;  ***********************
  84. ;  !!!!    WARNING    !!!!
  85. ;  ***********************
  86. ;
  87. ; Tampering with this source code can cause boot failures, lost data,
  88. ; and sad times.  Be smart, just say no.
  89. ;
  90. ;============================================================================
  91.  
  92.             code    segment
  93.             assume  cs:code
  94.  
  95.             org     100h
  96. entry:           jmp     main
  97.  
  98. ooem_name        db     8 dup (" ")             ;These values will be modified
  99. obytes_per_sec   dw     ?                       ;  by the install routine.
  100. osec_per_cluster db     ?
  101. oreserved_sec    dw     ?
  102. onumber_of_fats  db     ?
  103. oroot_size       dw     ?
  104. ototal_sec       dw     ?
  105. omedia_des_byte  db     ?
  106. osec_per_fat     dw     ?
  107. osec_per_track   dw     ?
  108. onumber_of_heads dw     ?
  109.  
  110. onum_hidden_sec dw      ?                       ;Added in DOS 3.x
  111.             dw      ?
  112. ototal_sec_long dd      ?                       ;Added in DOS 4.x
  113. odrive_number   db      ?
  114. oreserved       db      ?
  115. oextended_flag  db      ?
  116. ovol_serial     dd      ?
  117. ovol_name       db      11 dup (?)
  118. oreserved1      db      8 dup (?)
  119.  
  120. ;-----------------------------------------------------------------------
  121. ; Start of boot code
  122. ;-----------------------------------------------------------------------
  123. bootcode        proc    near
  124.             assume  ds:code
  125.             cli                ;Disable interrupts
  126.             cld                             ;Set direction UP.
  127.             xor     bx,bx
  128.             mov     ax,790h
  129.             mov     ss,ax                   ;SS:SP = 790:0
  130.             mov     sp,bx
  131.             sti                ;Interrupts OK
  132.             mov     bp,100h                 ;Set up BP for data addressing
  133.         mov    partition_ptrl,si    ;Save partition table ptr
  134.  
  135.             mov     ds,bx                   ;DS = 0
  136.             mov     es,ax                   ;ES = 790h
  137.             mov     di,bp              ;Move boot code out of the way
  138.             mov     si,7c00h                
  139.             mov     cx,256
  140.             rep     movsw
  141.  
  142.             push    es
  143.             mov     ax,offset boot_1
  144.             push    ax
  145.             retf
  146. boot_1:
  147.             push    cs
  148.             pop     ds                      ;DS = 790h
  149.             mov     boot_disk,dl            ;Save boot_disk
  150.  
  151.             mov    ax,bx            ;BX = 0
  152.             mov     al,number_of_fats       ;Compute the sector of the
  153.             mul     sec_per_fat             ;  root directory.
  154.             mov     cx,reserved_sec
  155.             add     cx,num_hidden_sec
  156.             adc     dx,num_hidden_sec[2]
  157.             mov     fat_sectorl,cx
  158.             mov     fat_sectorh,dx
  159.             add     cx,ax
  160.             adc     dx,bx                   ;BX = 0
  161.             mov     root_sectorl,cx
  162.             mov     root_sectorh,dx
  163.             mov     data_startl,cx
  164.             mov     data_starth,dx
  165.             push    dx
  166.  
  167.             mov     ax,32                   ;Get length of dir entry
  168.             mul     root_size               ;Compute the size -in sectors-
  169.             mov     si,bytes_per_sec        ;  of the Root Directory.
  170.             add     ax,si
  171.             dec     ax
  172.             div     si
  173.             add     data_startl,ax
  174.             adc     data_starth,bx
  175.             mov     root_bytes,ax           ;Save size of root dir
  176.  
  177.             xchg    ax,cx
  178.             pop     dx
  179.             mov     bx,ROOT_DIR
  180.             call    read_disk
  181.             jc      boot_error
  182.  
  183.             mov     si,offset mboot_name
  184.             call    load_and_boot
  185.             call    print_line        ;Print lost MBOOT.SYS msg
  186.  
  187.             mov     si,offset lastboot_name ;If fail, try old boot record
  188.             call    load_and_boot
  189. boot_error:
  190.             push    si
  191.             mov     si,offset bootfail_msg
  192.             call    print_line
  193.             pop     si
  194.             call    print_line
  195.  
  196. boot_halt:      jmp     short boot_halt
  197. bootcode        endp
  198.  
  199. ;-----------------------------------------------------------------------
  200. ; Read disk / Write Disk
  201. ; Entry: DX,AX - Absolute sector to read/write
  202. ;        BX - address of buffer.
  203. ;        CL - Number of sectors to read
  204. ; Exit:  CF - Clear if read successful.
  205. ;-----------------------------------------------------------------------
  206. write_disk      proc    near
  207.             mov     ch,3                    ;BIOS write disk
  208.             jmp     short read_0
  209. write_disk      endp
  210.  
  211. read_disk       proc    near
  212.             mov     ch,2                    ;BIOS read disk
  213. read_0:
  214.             push    di
  215.             mov     sectors2read,cl         ;Save number of sectors to read
  216.             mov     si,ax                   ;Save starting sector to read
  217.             mov     di,dx
  218.             mov     read_buff,bx
  219. read_1:
  220. ;Compute the Cylinder, Head, and Sector to read.
  221.             mov     ax,si            ;Get logical sector
  222.             mov     dx,di
  223.         mov    bx,sec_per_track    ;Get sectors per track
  224.             div     bx
  225.             inc     dx
  226.  
  227.         inc    bx
  228.         cmp    cl,4            ;Never read more than 4
  229.         jb    read_2            ;  sectors
  230.         mov    cl,4
  231. read_2:
  232.         push    dx
  233.         add    dl,cl            ;Prevent a disk read across
  234.         cmp    dx,bx            ;  a track boundry.
  235.         pop    dx
  236.         jbe    read_21
  237.         dec    cl
  238.         jmp    short read_2
  239. read_21:
  240.             mov     bx,dx                   ;Save sector
  241.             push    cx                      ;Save sectors to read
  242.  
  243.             cwd
  244.             div     number_of_heads         ;Compute head and cylinder
  245.             xchg    ah,al                   ;Swap cyl low and high bytes
  246.             mov     cl,6
  247.             shl     al,cl                   ;Shift high cyl bits
  248.             xchg    cx,ax                   ;Copy cyl into CX
  249.             or      cl,bl                   ;Combine cyl with sector
  250.             mov     dh,dl                   ;Move head number
  251.             pop     ax
  252.             mov     bh,5                    ;Try to read 5 times.
  253. read_3:
  254.             push    bx
  255.             push    ax
  256.             mov     bx,read_buff
  257.             mov     dl,boot_disk            ;Get disk to read
  258.         push    ax            ;Save sectors read
  259.             int     13h                     ;Read/Write disk.
  260.         pop    ax            ;Get sectors read
  261.         xor    ah,ah
  262.             jc      read_4                  ;Error, try again.
  263.             pop     cx                      ;Restore read/write cmd
  264.             pop     bx                      ;Restore retry count
  265.  
  266.             add     si,ax                   ;Update starting sector
  267.             adc     di,0
  268.             sub     sectors2read,al         ;Sub from total sectors to read
  269.             mul     bytes_per_sec           ;Move read buffer pointer
  270.             add     read_buff,ax
  271.             mov     cl,sectors2read
  272.             cmp     cl,0
  273.             ja      read_1
  274.             clc
  275. read_exit:
  276.             pop     di
  277.             ret
  278. read_4:
  279.             xor     ax,ax                   ;Reset disk before reading
  280.             int     13h
  281.             pop     ax
  282.             pop     bx
  283.             dec     bh
  284.             jnz     read_3
  285.             mov     si,offset readerr_msg
  286.             stc
  287.             jmp     short read_exit
  288. read_disk       endp
  289. ;-----------------------------------------------------------------------
  290. ; Find file - Searches the root directory for a filename.
  291. ; Entry: SI - Ptr to file name to find
  292. ; Exit:  CF - Clear if found.
  293. ;        DI - If CF clear, ptr to entry containing file name.
  294. ;-----------------------------------------------------------------------
  295. find_file       proc    near
  296.             mov     cx,root_size            ;Get number of entries
  297.             mov     di,ROOT_DIR
  298. findfile_1:
  299.             push    cx
  300.             push    si
  301.             push    di
  302.             mov     cx,11                   ;Compare names in entry
  303.             repe    cmpsb
  304.             pop     di
  305.             pop     si
  306.             pop     cx
  307.             je      findfile_2
  308.             add     di,32                   ;Point to next entry
  309.             loop    findfile_1
  310.             stc
  311.             ret
  312. findfile_2:
  313.             clc
  314.             ret
  315. find_file       endp
  316. ;-----------------------------------------------------------------------
  317. ; Print Line
  318. ; Entry: SI - Ptr to string to print.
  319. ;-----------------------------------------------------------------------
  320. print_line      proc    near
  321.             lodsb
  322.             or      al,al
  323.             je      findfile_2
  324.             mov     ah,0eh
  325.             mov     bx,7
  326.             int     10h
  327.             jmp     short print_line
  328. print_line      endp
  329.  
  330. ;-----------------------------------------------------------------------
  331. ; CLUSTER2SECTOR - Convert cluster number into sector number.
  332. ; Entry: AX - Cluster to read
  333. ; Exit:  AX - Sector number
  334. ;        CX - Cluster size
  335. ;-----------------------------------------------------------------------
  336. cluster2sector  proc    near
  337.             dec     ax            ;Compensate for 1st to FAT
  338.             dec     ax            ;  entries not being used.
  339.             xor     cx,cx                   ;Compute the starting sector
  340.             mov     cl,sec_per_cluster
  341.             mul     cx                      ;CX, number of sectors to read
  342.             add     ax,data_startl        
  343.             adc     dx,data_starth
  344.             ret
  345. cluster2sector  endp
  346.  
  347. ;-----------------------------------------------------------------------
  348. ; LOAD FIRST - Reads the first cluster of a file.
  349. ; Entry: BX - Destination buffer
  350. ;        DI - Ptr to directory entry
  351. ;-----------------------------------------------------------------------
  352. load_first    proc    near
  353.             mov     ax,[di+1ah]             ;Get starting cluster
  354.             mov     di,ax                   ;Save starting cluster
  355.             call    cluster2sector          ;Read 1st cluster.
  356.             call    read_disk
  357.         ret
  358. load_first    endp
  359.  
  360. ;-----------------------------------------------------------------------
  361. ; Load and Boot
  362. ; Entry: SI - Ptr to file name to load and boot
  363. ; Exit:  This routine will not return if boot file found.
  364. ;        CF - Set if boot file not found.
  365. ;        SI - Offset of error message.
  366. ;-----------------------------------------------------------------------
  367. load_and_boot   proc    near
  368.             assume  cs:code,ds:code
  369.             call    find_file               ;Find filename in dir list
  370.             jnc     lab_1
  371. lab_error:
  372.             mov     di,offset bootfile      ;Copy name of boot file
  373.             mov     cx,11                   ;  not found.
  374.             rep     movsb
  375.             xor     ax,ax                   ;Terminate string
  376.             stosb
  377.             mov     si,offset mbootlost_msg
  378.             ret
  379. lab_1:
  380.             mov     bx,300h                 ;Offset to load extended boot
  381.         call    load_first        ;Read first cluster of file
  382.             jc      lab_error
  383.  
  384.             pop     ax                      ;Remove local return address
  385.  
  386.         mov    dl,boot_disk
  387.         mov    si,partition_ptrl
  388.             xor     ax,ax                   ;Set up expected segment config
  389.             push    ax
  390.             mov     ah,7ch
  391.             push    ax
  392.             retf
  393. load_and_boot   endp
  394.  
  395. ;-----------------------------------------------------------------------
  396. ; Data used by the Boot record.
  397. ;-----------------------------------------------------------------------
  398. mboot_name      db      "MBOOT   SYS"
  399. lastboot_name   db      "LASTBOOTBIN"
  400. bootfail_msg    db      "Boot Failure",13,10,0
  401. readerr_msg     db      "Disk Error",0
  402. mbootlost_msg   db      "Can",27h,"t find file "
  403. bootfile        =       $
  404.             org     2FEh
  405.             dw      0aa55h                  ;Boot record flag
  406.  
  407. ;============================================================================
  408. ;============================================================================
  409. ; This part of Multiboot is loaded by the boot record.
  410. ;============================================================================
  411. ;============================================================================
  412. boot_extend_start =     $
  413.             jmp     boot_extend
  414.         org    303h
  415. boot_ptr_array    =    $
  416. boot_data_ptr    dw    offset boot_data1 - offset boot_extend_start
  417. boot_data_size    dw    offset boot_data1_end - offset boot_data1
  418. boot_sess_ptr    dw    offset boot_array - offset boot_extend_start
  419. boot_sess_size    dw    offset boot_array_end - offset boot_array
  420. boot_ostab_ptr    dw    offset opsys_table - offset boot_extend_start
  421. boot_ostab_size    dw    offset opsys_table_end - offset opsys_table
  422. boot_version    dw    05h
  423.  
  424. boot_data1      =    $
  425. last_choice     dw      1                       ;Boot session currently active
  426. last_opsys      db      1                       ;Last operating system booted.
  427. last_DOS    db    1            ;Last DOS version booted
  428.  
  429. boot_default    db      0                       ;Default boot session
  430. boot_timeout    dw      0                       ;Time until default
  431. opsys_clusters    dw    0            ;Size of original op sys files
  432. time_stamp    dd    0            ;Time stamp to verify disk.
  433. boot_data1_end   =    $
  434.  
  435. fat_seg_low    dw    FAT_SEGMENT1
  436. fat_seg_high    dw    FAT_SEGMENT2
  437. fat_mask        dw      0
  438. fat_size    dw    0
  439. load_error    db    "Boot extend load error",13,10,0
  440. ;-------------------------------------------------------------------------
  441. ; GET FATTYPE - Determines if the FAT is 12 bit or 16 bit.
  442. ; Entry:    BP - Pointer to boot data structure.
  443. ; Exit:     fat_mask initialized
  444. ;-------------------------------------------------------------------------
  445. get_fattype    proc    near
  446.             mov     si,0fff8h               ;Assume 16 bit FAT
  447.             xor     dx,dx
  448.             mov     ax,total_sec
  449.             or      ax,ax                   ;If total sectors = 0, huge
  450.             jne     get_fattype_1           ;  partition.
  451.             mov     ax,word ptr total_sec_long
  452.             mov     dx,word ptr total_sec_long[2]
  453. get_fattype_1:
  454.             xor     cx,cx                   ;If more than 4087 clusters,
  455.             mov     cl,sec_per_cluster      ;  assume 16 bit FAT.
  456.             div     cx
  457.             cmp     ax,4087        
  458.             ja      get_fattype_2
  459.             mov     si,0ff8h                ;Set 12 bit FAT mask
  460. get_fattype_2:
  461.         mov    fat_mask,si        ;Save FAT mask
  462.         mov    fat_size,ax
  463.         ret
  464. get_fattype    endp
  465.  
  466. ;-------------------------------------------------------------------------
  467. ; GET FAT ENTRY - Finds a FAT entry from index
  468. ; Entry:    BP - Pointer to boot data structure.
  469. ;           DI - Entry into FAT table
  470. ; Exit:     DI - Next entry
  471. ;           CF - Clear if last entry
  472. ;-------------------------------------------------------------------------
  473. get_fat_entry    proc    near
  474.         push    bx
  475.         push    ds
  476.         push    es
  477.         mov    dx,fat_mask        ;Get FAT mask 
  478.         mov    es,fat_seg_high        ;Load DS and ES with segments
  479.         mov    ds,fat_seg_low         ;  containing the FAT table.
  480.  
  481.             mov     bx,di                   ;Copy index number
  482.         add    bx,di
  483.         mov    ax,ds:[bx]        ;Assume low segment of 16 bit
  484.         jnc    get_fat_entry_1        ;  FAT.
  485.         mov    ax,es:[bx]        ;CF set, high segment
  486. get_fat_entry_1:
  487.             or      dx,dx                   ;Test for 12 or 16 bit FAT
  488.             js      get_fat_entry_3
  489.         mov    bx,di
  490.             shr     di,1                    ;12 bit FAT
  491.             mov     ax,ds:[bx+di]
  492.             jnc     get_fat_entry_2
  493.             mov     cl,4                    ;If odd index, shift
  494.             shr     ax,cl
  495. get_fat_entry_2:
  496.             and     ah,0fh                  ;Clear top nibble
  497. get_fat_entry_3:
  498.         mov    di,ax            ;Copy entry data
  499.             cmp     ax,dx            ;See if last entry
  500.         pop    es
  501.         pop    ds
  502.         pop     bx
  503.         ret
  504. get_fat_entry     endp
  505.  
  506. ;-------------------------------------------------------------------------
  507. ; LOAD FILE1 - Loads a file by reading the FAT table (Skips first cluster)
  508. ; Entry:    BP - Pointer to boot data structure.
  509. ;     ES:BX - Destination buffer
  510. ;           DI - Entry into FAT table
  511. ; Exit:     CF - Set if error
  512. ;-------------------------------------------------------------------------
  513. load_file1    proc    near
  514. load_file_1:
  515.         call    get_fat_entry
  516.         jnc     load_file_exit
  517.             push    bx
  518.             call    cluster2sector          ;Read next cluster
  519.             call    read_disk
  520.             pop     bx
  521.             jc      load_file_exit1
  522.         add    bx,bytes_per_clust    ;Update read destination
  523.         jmp    short load_file_1
  524. load_file_exit:
  525.         clc
  526. load_file_exit1:
  527.         ret
  528. load_file1    endp
  529.  
  530.  
  531. debug_msg5    db    ".",0
  532.  
  533. ;====================================================================
  534. ; BOOT EXTEND 
  535. ; Entry: DL - Boot Disk
  536. ;        SI - Pointer to booted partition table entry
  537. ;        DI - Starting cluster for this file
  538. ;====================================================================
  539. boot_extend     proc    near
  540.             mov     ax,790h                 ;Reload CS and DS.
  541.             mov     ds,ax
  542.             mov     es,ax
  543.             push    ax
  544.             mov     ax,offset extend_load_0    
  545.             push    ax
  546.             retf
  547. ;
  548. ; Since MBOOT.SYS may be larger than one cluster, the FAT table must be read
  549. ; and interpeted.  This next section of code must reside in the first
  550. ; 512 bytes of MBOOT.SYS.
  551. ;
  552. extend_load_0:
  553.         mov    hi_fat_size,0
  554.             mov     ax,sec_per_fat        ;Compute size of FAT
  555.         mov    cx,ax
  556.         mul    bytes_per_sec
  557.         or    dx,dx            ;See if larger than 64K
  558.         je     extend_load_1        ;Compute the max number of
  559.         mov    dx,1            ;  sectors in 64K.
  560.         xor    ax,ax
  561.         div    bytes_per_sec
  562.         mov    cx,ax            ;Copy sectors to read
  563. extend_load_1:
  564.          mov    low_fat_size,cx
  565.         mov    ax,FAT_SEGMENT1
  566.         mov    es,ax
  567.         xor    bx,bx
  568.             mov     ax,fat_sectorl          ;Get starting sector of FAT 
  569.             mov     dx,fat_sectorh
  570.         push    cx
  571.             call    read_disk        ;Read FAT 
  572.         pop    cx
  573.             jc      extend_read_error
  574.  
  575.         mov    ax,cx            ;If FAT larger than 64K
  576.         sub    cx,sec_per_fat        ;  read remainder into second
  577.         jbe    extend_load_2        ;  segment.
  578.          mov    hi_fat_size,cx
  579.         mov    bx,FAT_SEGMENT2
  580.         mov    es,bx
  581.         xor    bx,bx
  582.         mov    dx,bx
  583.             add     ax,fat_sectorl          ;Get ptr to remainder of FAT
  584.             adc     dx,fat_sectorh
  585.             call    read_disk        ;Read FAT 
  586.             jc      extend_read_error        
  587. extend_load_2:
  588.         push    cs            ;Restore ES
  589.         pop    es
  590.         call    get_fattype        ;See if 12 or 16 bit fat
  591.             xor     ax,ax
  592.             mov     al,sec_per_cluster
  593.             mul     bytes_per_sec
  594.         mov    bytes_per_clust,ax    ;Save bytes per cluster
  595.         mov    bx,ax              ;BX = dest for file data.  Add
  596.         add    bx,300h            ;  size of boot rec + 100h
  597.         call    load_file1        ;Read remainder of MBOOT.SYS
  598.             jnc     extend_load_3
  599. extend_read_error:
  600.         mov    si,offset load_error    ;Indicate load error
  601.             jmp     boot_error
  602. ;
  603. ; MBOOT.SYS fully loaded.  Get on with displaying the menu.
  604. ;
  605. extend_load_3:
  606.         mov    screen_rows,25        ;Configure screen
  607.         mov    normal_attr,COLOR_NORM
  608.         mov    highlight_attr,COLOR_HIGH
  609.         xor    ax,ax
  610.         int    11h            ;Get screen type
  611.             mov     bx,0003h                ;Set video mode 3
  612.         test    ax,10h            ;See if color or BW
  613.         jz    boot_extend_00
  614.             mov     bx,0007h                ;Set video mode 7
  615.         mov    normal_attr,BW_NORM
  616.         mov    highlight_attr,BW_HIGH
  617. boot_extend_00:    
  618.             mov     ax,bx            ;Set video mode.
  619.             call    vidint
  620.             call    write_box               ;Write copyright box
  621. boot_extend_01:
  622.             xor     ax,ax
  623.             mov     al,boot_default         ;Copy defaults
  624.             push    bp
  625.             mov     bp,offset boot_menu
  626.             mov     [bp+MENU_SELECTED],al
  627.             cmp     al,0                    ;If no default, no timeout
  628.             je      extend_load_02
  629.             mov     ax,boot_timeout
  630. extend_load_02:
  631.             mov     [bp+MENU_TIMEOUT],ax
  632.             call    menu
  633.             pop     bp
  634.             cmp     bl,0                    ;If no choice, ask again.
  635.             je      boot_extend_01
  636.  
  637.             call    scroll_half        ;Clear screen
  638.  
  639.             cmp     bx,last_choice          ;See if the choice is the same
  640.             jne     boot_extend_11          ;  as last time.
  641.             jmp     boot_extend_boot    ;Yes, boot with old files.
  642. boot_extend_11:
  643.         push    bx
  644.         call    get_entry        ;Get ptr to new entry    
  645.         mov    di,bx
  646.         pop    bx
  647.             xchg    last_choice,bx          ;Save new choice, get last
  648.             mov     old_choice,bx           ;Save in case of write error
  649.             call    get_entry               ;Compute offset of old entry
  650.  
  651.         mov    al,[di+OSTYPE_OFFSET]    ;If the operating system is
  652.         cmp    al,last_opsys        ;  different from the last 
  653.         je    boot_extend_2        ;  one, read the os files.
  654.  
  655.         mov    bl,al            ;See if OS/2 or DOS op sys.
  656.         call    get_os_entry        
  657.         cmp    word ptr [di+OPSYS_TYPE],100h    ;If OS/2 skip file
  658.         jae    boot_extend_22            ;  copying.
  659.  
  660.         cmp    al,last_DOS        ;If last DOS version same, 
  661.         je     boot_extend_22        ;  skip file copy.
  662.  
  663.         push    ax            ;Tell user we are changing
  664.         push    bx            ;  the DOS files.
  665.         mov    si,offset change_os_msg
  666.         call    write_linenorm
  667.         pop    bx
  668.         pop    ax
  669.  
  670.         mov    last_DOS,al
  671.         call    load_os_files        ;Read the DOS system files
  672.         mov    si,offset read_os_error
  673.         jc     boot_extend_write_error1
  674.  
  675.         call    write_os_files        ;Write DOS sys files to disk
  676.         jc    boot_extend_write_error1
  677.         push    ax
  678.         xor    ax,ax
  679.         mov    cx,ax
  680.         mov    cl,number_of_fats
  681. boot_extend_21:
  682.         call    write_fat_table        ;Write updated FAT to disk
  683.         inc    ax
  684.         loop    boot_extend_21
  685.         pop    ax
  686. boot_extend_22:
  687.         push    ax
  688.         mov    bl,last_opsys        ;Rename the boot record file
  689.         call    make_os_names        ;  to the name in the os table
  690.         mov    di,si
  691.         mov    si,offset lastboot_name
  692.         call    rename_file
  693.         pop    bx            ;Get back the new op sys type        
  694.         mov    last_opsys,bl
  695.         call    make_os_names        ;Rename the new boot file to
  696.         call    rename_file        ;  LASTBOOT.SYS
  697.  
  698.             mov     bx,old_choice        ;Get prev session
  699.             call    get_entry               ;Compute offset of old entry
  700. boot_extend_2:
  701.             lea     di,[bx+AUTO_OFFSET]    ;Rename the current AUTOEXEC
  702.             mov     si,offset autoexec_name    ;  file to its old name
  703.             call    rename_file
  704.  
  705.             lea     di,[bx+CONFIG_OFFSET]    ;Rename the current CONFIG.SYS
  706.             mov     si,offset config_name    ;  file to its old name.
  707.             call    rename_file
  708.  
  709.             mov     bx,last_choice          ;Rename saved files to
  710.             call    get_entry               ;  CONFIG.SYS and AUTOEXEC.BAT
  711.             lea     si,[bx+AUTO_OFFSET]     ;Start with AUTOEXEC.BAT
  712.             mov     di,offset autoexec_name
  713.             call    rename_file
  714.  
  715.             lea     si,[bx+CONFIG_OFFSET]   ;Now rename CONFIG.SYS
  716.             mov     di,offset config_name
  717.             call    rename_file
  718. boot_extend_3:
  719.             mov     ax,root_sectorl         ;Write the Root directory back
  720.             mov     dx,root_sectorh         ;  to the disk.
  721.             mov     bx,ROOT_DIR
  722.             mov     cx,root_bytes           ;Get size of root directory
  723.             call    write_disk
  724.             jnc     boot_extend_4           ;If write error,  Boot last
  725. boot_extend_write_error:
  726.             mov     si,offset boot_extend_err  ;  boot record.
  727. boot_extend_write_error1:
  728.             call    write_linenorm
  729.             mov     bx,old_choice
  730.             jmp     short boot_extend_boot
  731. boot_extend_4:
  732.             mov     si,offset mboot_name    ;Find MBOOT again in dir list
  733.             call    find_file
  734.             jc      boot_extend_write_error
  735.             mov     ax,[di+1ah]             ;Get starting cluster
  736.             mov     bx,300h
  737.             call    cluster2sector        ;Update the MBOOT boot table
  738.             call    write_disk
  739.             jc      boot_extend_write_error
  740.         mov    bx,last_choice
  741. boot_extend_boot:
  742.         call    get_entry        ;Print message to identify 
  743.         push    bx            ;  the session booting
  744.         mov    si,bx            
  745.         mov    di,offset boot_sess_msg1
  746.         mov    cx,NAME_LENGTH+1
  747.         rep    movsb
  748.         mov    si,offset boot_sess_msg    
  749.         call    write_linenorm
  750.         pop    bx
  751.  
  752.         mov    bl,[bx+OSTYPE_OFFSET]    ;Print message to identify 
  753.         call    get_os_entry        ;  operating system booting.
  754.         mov    si,offset boot_os_msg1
  755.         xchg    si,di
  756.         mov    cx,9
  757.         rep    movsb
  758.         mov    si,offset boot_os_msg
  759.         call    write_linenorm
  760.  
  761.         mov    dx,0d00h        ;Row 13, Column 0
  762.             call    set_cursor
  763.         mov    si,offset lastboot_name    ;Boot operating system.
  764.             call    load_and_boot
  765.             jmp     boot_halt        ;If this returns, halt
  766. boot_extend     endp
  767.  
  768. ;--------------------------------------------------------------------
  769. ; MENU querys the user menu selection.
  770. ; Entry: BP - Pointer to menu structure.
  771. ; Exit:  BX - Menu item selected.
  772. ;--------------------------------------------------------------------
  773. menu            proc    near
  774.             mov     last_timeout,0
  775.             mov     dx,[bp+MENU_TIMEOUT]    ;Point to timeout line
  776.             mov     timeout_value,dx        ;Copy timeout value
  777.             or      dx,dx                   ;If 0, no timeout
  778.             je      menu_wrtprompt
  779.             mov     si,offset timeout_str   ;Ptr to timeout string
  780.             call    write_linenorm
  781.  
  782.             xor     ax,ax                   ;Read system timer
  783.             int     1ah
  784.             add     dx,timeout_value        ;Set timeout value
  785.             mov     timeout_value,dx
  786. menu_wrtprompt:
  787.             mov     dx,[bp+MENU_PROMPT]     ;Write menu prompt
  788.             mov     si,offset prompt_text
  789.             call    write_line_at
  790. key_loop:
  791.             call    write_menu              ;Write menu choices
  792. key_loop_1:
  793.             mov     ax,timeout_value
  794.             cmp     ax,0                    ;If timout not disabled, print
  795.             jne     key_1                   ;  time remaining.
  796.             cmp     ax,last_timeout
  797.             je      key_2
  798.             mov     last_timeout,ax
  799.             mov     si,offset timetext1
  800.             call    write_linenorm
  801.             jmp     short key_2
  802. key_1:
  803.             xor     ax,ax                   ;Read system timer
  804.             int     1ah
  805.             mov     ax,timeout_value
  806.             sub     ax,dx                   ;Subtract current time
  807.             ja      key_11            ;If no time, exit with 
  808.             jmp     key_quit        ;  carry.
  809. key_11:
  810.             mov     cx,18
  811.             xor     dx,dx
  812.             div     cx
  813.             inc     ax
  814.             cmp     ax,last_timeout
  815.             je      key_2
  816.             mov     last_timeout,ax
  817.             mov     dx,173ch                ;Write time remaining
  818.             call    hex2asc
  819.         mov    dx,1a00h        ;Hide cursor
  820.         call    set_cursor
  821. key_2:
  822.         cmp    no_DOS_flag,0
  823.         je    key_3
  824.         int    28h            ;Call DOS idle
  825. key_3:
  826.         call    get_key            ;Get key from keyboard
  827.             jz      key_loop_1        ;No key available, loop
  828.  
  829.             cmp     al,0dh                  ;If CR, exit.
  830.             je      key_exit
  831.             cmp     al,27                   ;If ESC, quit.
  832.             je      key_quit
  833.             cmp     al,3                    ;If Ctl-C, quit.
  834.             je      key_quit
  835.  
  836.             cmp     al,31h                  ;If valid number jump
  837.             jb      key_down_0              ;  directly to selection.
  838.             cmp     al,39h
  839.             ja      key_down_0
  840.             sub     al,30h
  841.             call    check_valid             ;See if selection valid
  842.             jc      key_loop_1              ;No, get another key
  843.             jmp     short key_loop_2
  844. key_down_0:
  845.             cmp     al,9                    ;Tab
  846.             je      key_down_1
  847.             cmp     ah,4dh                  ;Right
  848.             je      key_down_1
  849.             cmp     ah,50h                  ;Down
  850.             jne     key_up_1
  851. key_down_1:
  852.             mov     al,[bp+MENU_SELECTED]
  853. key_down_2:
  854.             inc     al
  855.             cmp     al,[bp]
  856.             jbe     key_down_3
  857.             mov     al,1
  858. key_down_3:
  859.             call    check_valid             ;See if selection valid
  860.             jc      key_down_2
  861.             jmp     short key_loop_2
  862. key_up_1:
  863.             cmp     ax,0f00h                ;Back Tab
  864.             je      key_up_2
  865.             cmp     ah,4bh                  ;Left
  866.             je      key_up_2
  867.             cmp     ah,48h                  ;Up
  868.             je      key_up_2
  869.             jmp     key_loop_1
  870. key_up_2:
  871.             mov     al,[bp+MENU_SELECTED]
  872. key_up_3:
  873.             sub     al,1
  874.             ja      key_loop_2
  875.             mov     al,[bp]
  876. key_loop_2:
  877.             call    check_valid             ;See if selection valid
  878.             jc      key_up_3
  879.             mov     [bp+MENU_SELECTED],al
  880.             mov     timeout_value,0         ;Disable timeout
  881.             jmp     key_loop
  882. key_exit:            
  883.             clc
  884. key_exit1:
  885.             mov    bh,0
  886.             mov     bl,[bp+MENU_SELECTED]   ;Get menu item selected
  887.             ret
  888. key_quit:
  889.             stc
  890.             jmp     short key_exit1
  891. menu            endp
  892.  
  893. ;--------------------------------------------------------------------
  894. ; GET KEY  gets a key from the keyboard.
  895. ; Exit:  AX - key returned
  896. ;        ZF - Set if no key
  897. ;--------------------------------------------------------------------
  898. get_key         proc    near
  899.             mov     ah,1
  900.             int     16h                     ;Check for key
  901.             jz      get_key_1
  902.             mov     ah,0
  903.             int     16h                     ;Get key
  904.         or    ax,ax
  905. get_key_1:
  906.         ret
  907. get_key        endp
  908.  
  909. ;--------------------------------------------------------------------
  910. ; FETCH KEY  waits for and gets a key from the keyboard
  911. ; Exit:  AX - key returned
  912. ;--------------------------------------------------------------------
  913. fetch_key       proc    near
  914.         int    28h            ;Call DOS idle
  915.         call    get_key            ;Read a key from the keyboard
  916.         jz    fetch_key
  917.         ret
  918. fetch_key    endp
  919.  
  920. ;--------------------------------------------------------------------
  921. ; CHECK VALID determines if a menu selection is valid.
  922. ; Entry: BP - Pointer to menu structure.
  923. ;        AL - Menu selection
  924. ; Exit:  CF - Clear if valid selection
  925. ;--------------------------------------------------------------------
  926. check_valid     proc    near
  927.             push    ax
  928.             push    di
  929.             dec     al
  930.             cmp     al,[bp]                 ;See if beyond choices
  931.             ja      check_valid_bad
  932.             xor     ah,ah                   ;Convert selection into
  933.             shl     ax,1                    ;  index into menu structure
  934.             shl     ax,1
  935.             lea     di,[bp+MENU_FIRSTITEM]  ;Get ptr to 1st item
  936.             add     di,ax
  937.             mov     si,[di+2]               ;Get location of string
  938.             or      al,[si]                 ;If 1st byte > 80h, disabled
  939.             js      check_valid_bad         ;  item.
  940.             clc
  941. check_valid_exit:
  942.             pop     di
  943.             pop     ax
  944.             ret
  945. check_valid_bad:
  946.             stc
  947.             jmp     short check_valid_exit
  948. check_valid     endp
  949.  
  950. ;--------------------------------------------------------------------
  951. ; WRITE MENU displays the choices on the screen.
  952. ; Entry: BP - Pointer to menu structure.
  953. ;--------------------------------------------------------------------
  954. write_menu      proc    near
  955.             xor     cx,cx
  956.             mov     cl,[bp]                 ;Get number of choices
  957.             xor     bx,bx
  958.             lea     di,[bp+MENU_FIRSTITEM]  ;Get ptr to 1st item
  959. write_menu_1:
  960.             inc     bh                      ;Inc menu item counter
  961.  
  962.             mov     si,[di+2]               ;Get location of string
  963.             cmp     byte ptr [si],80h       ;If 1st byte > 80h, disabled
  964.             jae     write_menu_3            ;  item, don't print.
  965.  
  966.             mov     dx,[di]                 ;Get location of item
  967.             mov     al,bh                   ;Print menu item number
  968.             call    printnum
  969.  
  970.             add     dl,4
  971.             mov     si,[di+2]               ;Get location of string
  972.             cmp     bh,[bp+MENU_SELECTED]   ;If selected, use highlight
  973.             jne     write_menu_2            ;  attribute.
  974.             call    write_line_hi
  975.             jmp     short write_menu_3
  976. write_menu_2:
  977.             call    write_line_at
  978. write_menu_3:
  979.             add     di,4                    ;Point to next item
  980.             loop    write_menu_1
  981.  
  982.             mov     dx,[bp+MENU_PROMPT]
  983.             add     dl,8
  984.         call    set_cursor        ;Set cursor pos
  985.  
  986.             mov     al,[bp+MENU_SELECTED]   ;Get current selection
  987.             or      al,al
  988.             je      write_menu_exit
  989.             add     al,30h
  990.  
  991.             mov     ah,0ah                  ;BIOS Write Char
  992.             mov     cx,1                    ;1 character
  993.         xor    bx,bx
  994.             call    vidint
  995. write_menu_exit:
  996.             ret
  997. write_menu      endp
  998.  
  999. ;--------------------------------------------------------------------
  1000. ; GETENTRY - Computes the offset of a boot array entry given the
  1001. ;            entry number
  1002. ; Entry: BL - Entry number
  1003. ; Exit:  BX - Offset of that entry
  1004. ;--------------------------------------------------------------------
  1005. get_entry       proc    near
  1006.             mov     ax,offset boot_array    
  1007. get_entry1:
  1008.         push    ax            ;Save start of table
  1009.             dec     bx
  1010.             mov     al,NEXT_ENTRY           ;Multiply the size of
  1011.             mul     bl                      ;  each entry by the
  1012.             pop     bx                      ;  number then add the
  1013.             add     bx,ax                   ;  starting offset.
  1014.             ret
  1015. get_entry       endp
  1016.  
  1017. ;--------------------------------------------------------------------
  1018. ; GET OS ENTRY - Computes offset of entry in the op sys table.
  1019. ; Entry: BL - Operating system number. 1 - 4
  1020. ; Exit:  DI - Pointer to entry in op sys table.
  1021. ;--------------------------------------------------------------------
  1022. get_os_entry    proc    near
  1023.         push    ax
  1024.         push    bx
  1025.         xor    bh,bh
  1026.         dec    bl
  1027.         mov    al,NEXT_OSENTRY
  1028.         mul    bl
  1029.         add    ax,offset opsys_table
  1030.         mov    di,ax
  1031.         pop    bx
  1032.         pop    ax
  1033.         ret
  1034. get_os_entry    endp
  1035.  
  1036. ;--------------------------------------------------------------------
  1037. ; LOAD_FILE - Computes offset of entry in the op sys table.
  1038. ; Entry: ES:BX - Destination buffer
  1039. ;           DI - Ptr to directory table entry 
  1040. ;           BP - Boot data ptr
  1041. ;--------------------------------------------------------------------
  1042. load_file    proc    near
  1043.         push    bx
  1044.         call    load_first
  1045.         pop    bx
  1046.         add    bx,bytes_per_clust
  1047.         call    load_file1
  1048.         ret
  1049. load_file    endp
  1050.  
  1051. ;--------------------------------------------------------------------
  1052. ; LOAD_OS_FILES - Reads the operating system files into memory.
  1053. ; Entry: AL - Operating system number
  1054. ;        BP - Boot data ptr
  1055. ;--------------------------------------------------------------------
  1056. load_os_files    proc    near
  1057.         push    ax
  1058.         push    bx
  1059.         mov    bl,al
  1060.         call    make_os_names        ;Make op sys names
  1061.         add    si,11            ;Point to IO.SYS name
  1062.         call    find_file        ;Find the filename
  1063.         jc    load_os_files_exit
  1064.         mov    cx,[di+1ch]        ;Read file size
  1065.         mov    new_io_size,cx
  1066.         push    di
  1067.         add    si,11            ;Point to MSDOS.SYS
  1068.         call    find_file        ;Find the filename
  1069.         mov    si,di
  1070.         pop    di
  1071.         jc    load_os_files_exit
  1072.         mov    cx,[si+1ch]        ;Read file size
  1073.         mov    new_dos_size,cx
  1074.         
  1075.         mov    ax,DATA_SEG1
  1076.         mov     es,ax
  1077.         xor    bx,bx
  1078.         push    si
  1079.         call    load_file        ;Read IO.SYS
  1080.         pop    di
  1081.         jc    load_os_files_exit
  1082.         mov    ax,DATA_SEG2
  1083.         mov     es,ax
  1084.         xor    bx,bx
  1085.         call    load_file        ;Read MSDOS.SYS        
  1086. load_os_files_exit:
  1087.         push    cs            ;Restore ES
  1088.         pop    es
  1089.         pop    bx
  1090.         pop    ax
  1091.         ret
  1092. load_os_files    endp
  1093.  
  1094. ;--------------------------------------------------------------------
  1095. ; WRITE_OS_FILES - Writes the operating system files onto the disk.
  1096. ; Entry: BP - Boot data ptr
  1097. ;        AL - Operating system number
  1098. ;--------------------------------------------------------------------
  1099. write_os_files    proc    near
  1100.         push    ax
  1101.         push    bx
  1102.  
  1103.         mov    bx,ax            ;Copy os number
  1104.         call    get_os_entry
  1105.         mov    cx,[di+OPSYS_TYPE]    ;Get os config    
  1106.  
  1107.         cmp    cx,50h             
  1108.         je    write_os_files_0
  1109.         mov    ax,1            ;At least 1 cluster needed
  1110.          cmp    cx,40h             ;  for DOS 4 type os
  1111.          jae    write_os_files_02
  1112.  
  1113.         mov    ax,new_io_size        ;Get clusters needed for
  1114.         xor    dx,dx            ;  files.
  1115.         div    bytes_per_clust        
  1116.         inc    ax
  1117.         push    ax            ;Save clusters for IO.SYS
  1118.  
  1119.         xor    ax,ax
  1120.         cmp    cx,30h            ;If DOS 3 type os, only IO.SYS
  1121.         jae    write_os_files_01    ;  size needs to be checked
  1122.         mov    ax,new_dos_size        
  1123.         xor    dx,dx
  1124.         div    bytes_per_clust        
  1125.         inc    ax
  1126. write_os_files_01:
  1127.         pop    dx            ;Get IO.SYS clusters needed
  1128.         add    ax,dx
  1129. write_os_files_02:
  1130.         push    ax            ;Save clusters needed
  1131.         push    bx
  1132.         call    check_fat        ;See if enough room for opsys
  1133.         pop    bx            ;  files.
  1134.         pop    dx            
  1135.         cmp    dx,cx
  1136.         mov    si,offset no_room_error
  1137.         ja    write_os_files_err1
  1138. write_os_files_0:
  1139.         mov    cx,new_io_size        ;Get size of new IO.SYS
  1140.         add    di,9             ;Point to IO.SYS name
  1141.         mov    si,di            ;Copy entry in op sys table
  1142.  
  1143.         mov    di,ROOT_DIR        ;Get ptr to root dir
  1144.         push    cx
  1145.         push    di
  1146.         call    clear_file        ;Remove IO.SYS from FAT
  1147.         add    di,20h            ;Point to next file
  1148.         call    clear_file        ;Remove MSDOS.SYS from FAT
  1149.         call    clean_fat        ;Remove any bad cluster flags
  1150.         
  1151.         mov    ax,DATA_SEG1        ;Get seg of IO.SYS data
  1152.         mov    es,ax
  1153.         mov    dx,1            ;Look for 1st free cluster.
  1154.         call    find_free_clust
  1155.         mov    dx,di        
  1156.         pop    di
  1157.         pop    cx
  1158.         call    store_os_file        ;Write IO.SYS to disk
  1159.         jc    write_os_files_exit
  1160.  
  1161.         add    di,20h            ;Point to next dir entry
  1162.         add    si,11            ;Point to MSDOS.SYS name
  1163.  
  1164.         mov    cx,new_dos_size        ;Get size of new MSDOS.SYS    
  1165.         mov    ax,DATA_SEG2        ;Get seg of MSDOS.SYS data
  1166.         mov    es,ax
  1167.         call    store_os_file        ;Write MSDOS.SYS to disk
  1168.         jc    write_os_files_exit
  1169.  
  1170.         mov    bx,opsys_clusters    ;Get number of sys sectors
  1171.         inc    bx
  1172.         mov    di,dx
  1173.         mov    ax,0fff7h        ;Bad sector flag
  1174.         cmp    bx,di
  1175.         jb    write_os_files_2
  1176. write_os_files_1:
  1177.         call    write_fat_entry        ;Fill in empty sectors with
  1178.         inc    di            ;  bad sector flags.
  1179.         cmp    bx,di
  1180.         jae    write_os_files_1
  1181. write_os_files_2:
  1182.         clc
  1183. write_os_files_exit:
  1184.         push    cs            ;Restore ES
  1185.         pop    es
  1186.         pop    bx
  1187.         pop    ax
  1188.         ret
  1189. write_os_files_err:
  1190.         mov    si,offset write_os_error
  1191. write_os_files_err1:
  1192.         stc
  1193.         jmp    short write_os_files_exit
  1194. write_os_files    endp
  1195.  
  1196. ;-----------------------------------------------------------------------
  1197. ; STORE OS FILE - Writes an operating system file to the disk
  1198. ; Entry: DX - Starting Cluster of file
  1199. ;        CX - Size of file
  1200. ;        SI - New file name
  1201. ;        DI - Ptr to directory entry
  1202. ;        ES - Segment of file data
  1203. ; Exit:     DX - Next free cluster
  1204. ;     CF - Set if error
  1205. ;-----------------------------------------------------------------------
  1206. store_os_file    proc    near
  1207.         push    di
  1208.         push    si
  1209.         push    es
  1210.         push    ds
  1211.         pop    es
  1212.         push    di            ;First, copy new name to
  1213.         push    cx            ;  dir entry. 
  1214.         mov    cx,11            
  1215.         rep    movsb
  1216.         pop    cx
  1217.         pop    di
  1218.         pop    es
  1219.  
  1220.         mov    [di+1Ah],dx        ;Save new starting cluster
  1221.         mov    [di+1Ch],cx        ;Save size in dir entry
  1222.         xor    bx,bx            ;Start at beginning of buffer
  1223. store_os_file_1:
  1224.         mov    ax,dx            ;Copy cluster to write
  1225.         push    bx
  1226.         push    cx
  1227.         push    dx
  1228.         call    cluster2sector        ;Convert to sector number
  1229.         call    write_disk        ;Write cluster to disk
  1230.         pop    dx
  1231.         pop    cx
  1232.         pop    bx
  1233.         add    bx,bytes_per_clust    ;Update read dest
  1234.         sub    cx,bytes_per_clust    ;Sub bytes  written from size
  1235.         ja    store_os_file_11
  1236.         mov    di,dx            ;Get new cluster
  1237.         mov    ax,-1            ;Write -1 to FAT entry to
  1238.         call    write_fat_entry        ;  indicate end of file.
  1239.         call    find_free_clust        ;Get next free cluster
  1240.         mov    dx,di            ;Copy ptr to free cluster
  1241. store_os_file_exit:
  1242.         pop    si
  1243.         pop    di
  1244.         ret
  1245. store_os_file_11:
  1246.         call    find_free_clust        ;Get next free cluster
  1247.         jc    store_os_file_exit
  1248.         mov    ax,di            ;Copy new FAT entry
  1249.         xchg    di,dx            ;Xchg old, new FAT entries    
  1250.         call    write_fat_entry        ;Write new cluster to old FAT
  1251.         jmp    short store_os_file_1    ;  entry.  Loop back for more.
  1252. store_os_file    endp
  1253.  
  1254. ;-----------------------------------------------------------------------
  1255. ; FIND FREE CLUST - Finds the next free cluster in the FAT
  1256. ; Entry: DX - Current cluster
  1257. ; Exit:     DI - Next free cluster
  1258. ;        CF - Set if no free clusters
  1259. ;-----------------------------------------------------------------------
  1260. find_free_clust    proc    near
  1261.         push    dx            
  1262. find_free_clust_1:
  1263.         inc    dx            ;First, check to see if at 
  1264.         cmp    fat_size,dx        ;  end of FAT.
  1265.         jb     find_free_clust_exit
  1266.  
  1267.         mov    di,dx            ;Scan through FAT to find next
  1268.         push    dx            ;  entry with 0, indicating
  1269.         call    get_fat_entry        ;  free cluster.    
  1270.         pop    dx
  1271.         or     di,di            ;See if cluster = 0 -> free
  1272.         jne    find_free_clust_1    ;No, keep looking
  1273.         mov    di,dx            ;Copy free cluster 
  1274.         clc
  1275. find_free_clust_exit:
  1276.         pop    dx
  1277.         ret
  1278. find_free_clust    endp
  1279.  
  1280. ;-----------------------------------------------------------------------
  1281. ; CHECK FAT - Counts the number of consecutive clusters at the start of
  1282. ;             the disk.
  1283. ; Exit:     CX - Count of available clusters.
  1284. ;-----------------------------------------------------------------------
  1285. check_fat     proc    near
  1286.         push    di
  1287.         mov    di,ROOT_DIR
  1288.         mov    bx,[di+1Ah]        ;Get starting cluster.  If not
  1289.         call    get_fat_chain        ;  consecutive clusters, skip
  1290.         jc    check_fat_1        ;  msdos.sys check.
  1291.         inc    bx
  1292.         mov    si,bx            ;Save ending cluster
  1293.         add    di,20h            ;Point to MSDOS.SYS entry
  1294.         mov    bx,[di+1Ah]        ;Get starting cluster
  1295.         cmp    si,bx
  1296.         jne    check_fat_6    
  1297.         call    get_fat_chain
  1298.         add    cx,si            ;Sum consec clusters.
  1299. check_fat_1:
  1300.         inc    bx
  1301.         mov    ax,fat_mask        ;Convert FAT mask into bad
  1302.         mov    al,0f7h            ;  sector detector
  1303. check_fat_2:
  1304.         mov    di,bx            ;Copy ptr to last FAT entry
  1305.         push    cx
  1306.         push    ax            ;Count the number of bad
  1307.         call    get_fat_entry        ;  sectors at the end of 
  1308.         pop    ax            ;  the system files.
  1309.         pop    cx
  1310.         or    di,di            ;See if sector free.
  1311.         je    check_fat_3
  1312.         cmp    di,ax            ;See if sector marked bad
  1313.         jne    check_fat_4
  1314. check_fat_3:
  1315.         inc    bx            ;Inc FAT pointer
  1316.         inc    cx            ;Inc Count
  1317.         jmp    short check_fat_2
  1318. check_fat_4:
  1319.         clc
  1320. check_fat_5:
  1321.         pop    di
  1322.             ret
  1323. check_fat_6:
  1324.         stc
  1325.         jmp    short check_fat_1
  1326. check_fat    endp
  1327.  
  1328. ;-----------------------------------------------------------------------
  1329. ; CLEAN FAT - Removes bad cluster markers used to reserve clusters.
  1330. ;-----------------------------------------------------------------------
  1331. clean_fat    proc    near
  1332.         mov    di,2            ;Start at cluster 2
  1333.         mov    bx,fat_mask
  1334.         and    bl,0f7h            ;Create Bad entry mask
  1335.         or    bl,0f7h
  1336. clean_fat_1:
  1337.         push    di
  1338.         call    get_fat_entry        ;See if entry marked bad
  1339.         cmp    di,bx
  1340.         pop    di
  1341.         jne    clean_fat_2        ;No, skip write.
  1342.         xor    ax,ax    
  1343.         call    write_fat_entry        ;Clear entry
  1344. clean_fat_2:
  1345.         inc    di            ;Point to next entry
  1346.         mov    ax,opsys_clusters
  1347.         add    ax,2
  1348.         cmp    di,ax
  1349.         jbe    clean_fat_1
  1350.         ret
  1351. clean_fat    endp
  1352.  
  1353. ;-----------------------------------------------------------------------
  1354. ; GET FAT CHAIN - Follows a FAT chain for a file.
  1355. ; Entry: BX - Ptr to start of chain
  1356. ; Exit:  CX - Count of consecutive clusters
  1357. ;        BX - Last entry in FAT table.
  1358. ;        CF - Set if file not in consecutive clusters
  1359. ;-----------------------------------------------------------------------
  1360. get_fat_chain    proc    near
  1361.         push    di
  1362.         xor    cx,cx
  1363.         mov    di,bx
  1364. get_fat_chain_1:
  1365.         inc    cx
  1366.         mov    bx,di            ;Copy FAT entry ptr
  1367.         push    cx
  1368.         call    get_fat_entry
  1369.         pop    cx
  1370.         mov    ax,bx
  1371.         jnc     get_fat_chain_2        ;CF = 0, last entry
  1372.         sub    bx,di            ;See if consecutive
  1373.         cmp    bx,-1
  1374.         je    get_fat_chain_1
  1375.         stc
  1376. get_fat_chain_2:
  1377.         mov    bx,ax            ;Get back last FAT entry
  1378.         pop    di
  1379.             ret
  1380. get_fat_chain    endp
  1381.  
  1382. ;-------------------------------------------------------------------------
  1383. ; CLEAR FILE - Removes the FAT table entries for a file.
  1384. ; Entry:    BP - Pointer to boot data structure.
  1385. ;           DI - Pointer to directory entry
  1386. ;-------------------------------------------------------------------------
  1387. clear_file    proc    near
  1388.         push    di
  1389.         push    si
  1390.         mov    bx,[di+1Ah]        ;Get starting cluster
  1391. clear_file_1:
  1392.         mov    di,bx            ;Save FAT pointer
  1393.         call    get_fat_entry
  1394.         pushf                ;Save end of file flag
  1395.         xchg    di,bx
  1396.         xor    ax,ax
  1397.         call    write_fat_entry        ;Zero entry to free cluster
  1398.         popf    
  1399.         jc    clear_file_1
  1400.         pop    si
  1401.         pop    di
  1402.         ret
  1403. clear_file    endp
  1404.  
  1405. ;-------------------------------------------------------------------------
  1406. ; WRITE FAT ENTRY - Writes FAT table entry 
  1407. ; Entry:    BP - Pointer to boot data structure.
  1408. ;           DI - Pointer to fat table entry
  1409. ;           AX - Data to write to FAT table
  1410. ;-------------------------------------------------------------------------
  1411. write_fat_entry    proc    near
  1412.         push    ax
  1413.         push    bx
  1414.         push    dx
  1415.         push    di
  1416.         push    ds
  1417.         push    es
  1418.  
  1419.         mov    ds,fat_seg_low         ;Load DS and ES with segments
  1420.         mov    es,fat_seg_high        ;  containing the FAT table.
  1421.  
  1422.         mov    dx,cs:fat_mask        ;Mask data to FAT size.
  1423.         or    dl,-1
  1424.         and    ax,dx
  1425.         xor    dx,dx        
  1426.         or     dx,cs:fat_mask        ;Mask unwanted bits
  1427.         jns    write_fat_4        ;If 0fffh, 12 bit FAT
  1428.             mov     bx,di                   ;16 bit FAT
  1429.         add    di,bx            ;Ptr = Index * 2
  1430.         jnc    write_fat_2        ;CF = 1, Upper segment
  1431. write_fat_1:
  1432.         mov    es:[di],ax        ;Write data
  1433.         jmp    short write_fat_3
  1434. write_fat_11:
  1435.         or    ax,bx
  1436. write_fat_2:
  1437.         mov    ds:[di],ax        ;Write data
  1438. write_fat_3:
  1439.         pop    es
  1440.         pop    ds
  1441.         pop    di
  1442.         pop    dx
  1443.         pop    bx
  1444.         pop    ax
  1445.         ret
  1446. write_fat_4:
  1447.         mov    bx,di
  1448.             shr     di,1                    ;12 bit FAT
  1449.         pushf
  1450.         add    di,bx
  1451.         mov    bx,ds:[di]        ;Get data
  1452.         popf
  1453.         jc    write_fat_5        ;Jump if odd
  1454.         and    bx,0f000h        ;Remove old data
  1455.         jmp    short write_fat_11
  1456. write_fat_5:
  1457.         and    bx,000fh        ;Remove old data
  1458.         push    cx
  1459.         mov    cl,4
  1460.         shl    ax,cl
  1461.         pop    cx
  1462.         jmp    short write_fat_11
  1463. write_fat_entry    endp
  1464.  
  1465. ;-----------------------------------------------------------------------
  1466. ; WRITE FAT TABLE - Writes data in memory FAT to disk FAT.
  1467. ; Entry: AX - FAT number to write
  1468. ;-----------------------------------------------------------------------
  1469. write_fat_table    proc    near
  1470.         push    ax
  1471.         push    cx
  1472.         push    es
  1473.         mov    cx,sec_per_fat        ;Compute starting sector
  1474.         mul    cx            ;  of this FAT
  1475.             add     ax,fat_sectorl          
  1476.             adc     dx,fat_sectorh
  1477.  
  1478.         push    ax
  1479.         push    dx
  1480.         mov    bx,FAT_SEGMENT1
  1481.         mov    es,bx
  1482.         xor    bx,bx
  1483.         mov    cx,low_fat_size
  1484.             call    write_disk        ;Write FAT 
  1485.         pop    dx
  1486.         pop    ax
  1487.             jc      write_fat_table_exit
  1488.  
  1489.         xor    cx,cx
  1490.         or     cx,hi_fat_size
  1491.         je    write_fat_table_exit
  1492.         add    ax,cx
  1493.         adc    dx,0
  1494.         mov    bx,FAT_SEGMENT2
  1495.         mov    es,bx
  1496.         xor    bx,bx
  1497.         call    write_disk
  1498. write_fat_table_exit:
  1499.         pop    es
  1500.         pop    cx
  1501.         pop    ax
  1502.         ret
  1503. write_fat_table    endp
  1504.  
  1505. ;-----------------------------------------------------------------------
  1506. ; RENAME FILE
  1507. ; Entry: SI - Ptr to file name to find
  1508. ;        DI - Ptr to new file name.
  1509. ;-----------------------------------------------------------------------
  1510. rename_file     proc    near
  1511.             push    di
  1512.         push    si
  1513.             cmp     byte ptr [di],0         ;See if filename exists
  1514.             je      rename_1
  1515.             push    di                      ;Save ptr to new file name
  1516.             call    find_file
  1517.             pop     si
  1518.             jc      rename_1
  1519.             mov     cx,11                   ;Copy name to entry.
  1520.             rep     movsb
  1521.             clc
  1522. rename_1:
  1523.             pop     di
  1524.         pop    si
  1525.             ret
  1526. rename_file     endp
  1527.  
  1528. ;-----------------------------------------------------------------------
  1529. ; MAKE OS NAMES
  1530. ; Entry: BL - Operating System number
  1531. ; Exit:  SI - Ptr array of 8.3 op sys names
  1532. ;-----------------------------------------------------------------------
  1533. make_os_names   proc    near
  1534.         push    bx
  1535.         mov    si,offset os_names_table
  1536.         add    bl,"0"
  1537.         mov    [si+7],bl
  1538.         mov    [si+18],bl
  1539.         mov    [si+29],bl
  1540.             pop     bx
  1541.             ret
  1542. make_os_names   endp
  1543.  
  1544. ;--------------------------------------------------------------------
  1545. ; WRITE VERT
  1546. ;--------------------------------------------------------------------
  1547. write_vert      proc    near
  1548.             lodsw                           ;Get location
  1549.             mov     dx,ax
  1550. write_vert1:
  1551.             mov     di,dx                   ;Save cursor pos
  1552.             call    set_cursor
  1553.             lodsb
  1554.             or      al,al
  1555.             je      write_vert2
  1556.             mov     ah,0ah                  ;BIOS Write Char
  1557.             mov     cx,1                    ;1 character
  1558.             call    vidint
  1559.             mov     dx,di                   ;Get cursor pos
  1560.             inc     dh
  1561.             call    set_cursor
  1562.             jmp     short write_vert1
  1563. write_vert2:
  1564.             ret
  1565. write_vert      endp
  1566.  
  1567. ;--------------------------------------------------------------------
  1568. ; WRITE LINENORM
  1569. ;Entry: SI - Offset of ASCIIZ string with leading word detailing
  1570. ;            row and column to start string.
  1571. ;--------------------------------------------------------------------
  1572. write_linenorm  proc    near
  1573.             push    dx
  1574.             lodsw                           ;Get location
  1575.             mov     dx,ax
  1576.             call    write_line_at
  1577.             pop     dx
  1578.             ret
  1579. write_linenorm  endp
  1580.  
  1581. ;--------------------------------------------------------------------
  1582. ; WRITE LINE AT/HI
  1583. ;Entry: DX - Row/Column to start string
  1584. ;       SI - Offset of ASCIIZ string
  1585. ;--------------------------------------------------------------------
  1586. write_line_hi   proc    near
  1587.             mov     bl,highlight_attr       ;Write with highlight attribute
  1588.             jmp     short write_line_at1
  1589. write_line_hi   endp
  1590.  
  1591. write_line_at   proc    near
  1592.             mov     bl,normal_attr
  1593. write_line_at1:
  1594.             call    set_cursor
  1595.             call    write_line
  1596.             ret
  1597. write_line_at   endp
  1598.  
  1599. ;--------------------------------------------------------------------
  1600. ; WRITE LINE
  1601. ;Entry: BL - Attribute for line
  1602. ;       SI - Offset of ASCIIZ string
  1603. ;--------------------------------------------------------------------
  1604. write_line      proc    near
  1605.             push    bx
  1606.             push    cx
  1607.             push    dx
  1608.             push    di
  1609.             xor     bh,bh                   ;Set video page
  1610.             mov     di,dx                   ;Save cursor pos
  1611. write_line_1:
  1612.             lodsb
  1613.             or      al,al
  1614.             je      write_line_2
  1615.             mov     ah,09h                  ;BIOS Write Char/Attr
  1616.             mov     cx,1                    ;1 character
  1617.             call    vidint
  1618.             inc     di
  1619.             mov     dx,di                   ;Get cursor pos
  1620.             call    set_cursor
  1621.             jmp     short write_line_1
  1622. write_line_2:
  1623.             pop     di
  1624.             pop     dx
  1625.             pop     cx
  1626.             pop     bx
  1627.             ret
  1628. write_line      endp
  1629.  
  1630. ;--------------------------------------------------------------------
  1631. ;WRITE BORDER
  1632. ;--------------------------------------------------------------------
  1633. write_border    proc    near
  1634.             call    set_cursor
  1635.             mov     ax,0acdh                ;Write border
  1636.             mov     cx,59
  1637.             call    vidint
  1638.             ret
  1639. write_border    endp
  1640.  
  1641. ;--------------------------------------------------------------------
  1642. ; WRITE BOX writes copyright box to the screen.
  1643. ;--------------------------------------------------------------------
  1644. write_box       proc near
  1645.             call    scroll_scr
  1646.         xor    bx,bx
  1647.         mov     bl,normal_attr
  1648.             mov     dx,010bh
  1649.             call    write_border
  1650.             mov     dx,050bh
  1651.             call    write_border
  1652.  
  1653.             mov     si,offset box1
  1654.             call    write_vert
  1655.             mov     si,offset box2
  1656.             call    write_vert
  1657.  
  1658.             mov     si,offset boxtext1      ;Point to 1st line
  1659.             mov     cx,3
  1660. title1:         mov     bl,normal_attr          ;Set attribute
  1661.             call    write_linenorm
  1662.             loop    title1
  1663.             ret
  1664. write_box       endp
  1665.  
  1666. ;-----------------------------------------------------------------------------
  1667. ; VIDINT - Calls the BIOS int 10h.  Saves BP to correct bug in old PC BIOS.
  1668. ;-----------------------------------------------------------------------------
  1669. vidint          proc near
  1670.             push    bp
  1671.             int     10h
  1672.             pop     bp
  1673.             ret
  1674. vidint          endp
  1675.  
  1676. ;-----------------------------------------------------------------------------
  1677. ; SCROLL SCR Clears the screen.
  1678. ;-----------------------------------------------------------------------------
  1679. scroll_scr      proc    near
  1680.             xor     cx,cx
  1681.         mov    dh,screen_rows
  1682.             mov     dl,50h
  1683.             call    scroll_block
  1684.             ret
  1685. scroll_scr      endp
  1686.  
  1687. ;-----------------------------------------------------------------------------
  1688. ; SCROLL HALF Clears the screen below the copyright box.
  1689. ;-----------------------------------------------------------------------------
  1690. scroll_half     proc    near
  1691.             mov     cx,0700h                ;Row 7 Col 0
  1692.             mov     dx,1950h
  1693.             call    scroll_block
  1694.             ret
  1695. scroll_half     endp
  1696.  
  1697. ;-----------------------------------------------------------------------------
  1698. ; SCROLL BLOCK Clears a part of the screen.
  1699. ; Entry: CX - Upper left corner
  1700. ;        DX - Lower right corner
  1701. ;-----------------------------------------------------------------------------
  1702. scroll_block    proc    near
  1703.             push    bx
  1704.             xor     bx,bx
  1705.             mov     bh,normal_attr
  1706.             mov     ax,0600h                ;Scroll up
  1707.             call    vidint
  1708.             pop     bx
  1709.             ret
  1710. scroll_block    endp
  1711.  
  1712. ;-----------------------------------------------------------------------------
  1713. ; SCROLL BLOCK Clears a part of the screen.
  1714. ; Entry: DX - Cursor Location
  1715. ;-----------------------------------------------------------------------------
  1716. set_cursor      proc    near
  1717.         push    ax
  1718.         push    bx
  1719.             mov     ah,02h                  ;Set cursor
  1720.             xor     bx,bx
  1721.             call    vidint
  1722.         pop    bx
  1723.         pop    ax
  1724.         ret
  1725. set_cursor      endp
  1726.  
  1727. ;-----------------------------------------------------------------------------
  1728. ; PRINTNUM - Prints a single digit number to the screen.
  1729. ; Entry:  AL - binary number
  1730. ;         DX - Cursor location
  1731. ;-----------------------------------------------------------------------------
  1732. printnum        proc    near
  1733.             add     al,30h
  1734.             mov     si,offset number_buff
  1735.             mov     [si],al
  1736.             call    write_line_at           ;Write number
  1737.             ret
  1738. printnum        endp
  1739.  
  1740. ;-----------------------------------------------------------------------------
  1741. ; HEX2ASC converts a binary number to ASCII and prints it to the screen.
  1742. ; Entry:  AX - binary number
  1743. ;-----------------------------------------------------------------------------
  1744. hex2asc         proc    near
  1745.             call    set_cursor
  1746.         xor    cx,cx
  1747.         mov    cl,1            ;If number = 0, print 1
  1748.         or    ax,ax            ;  zero.
  1749.         jne    hex_0
  1750.         mov    al,"0"
  1751.         jmp    short hex_1
  1752. hex_0:
  1753.             mov     cl,3                    ;Allow max of three digits
  1754. hex_loop1:
  1755.             xor     dx,dx                   ;Clear high word
  1756.             mov     bx,10                   ;Load number base
  1757.             div     bx                      ;Divide by base (10)
  1758.             add     dl,30h                  ;Convert to ascii
  1759.             push    dx                      ;Save digit on stack
  1760.             loop    hex_loop1
  1761.             mov     cx,3                    ;Allow max of three digits
  1762.             mov     bl,"0"                  ;Set leading zero indicator
  1763. hex_loop2:
  1764.             pop     ax                      ;Get digit off stack
  1765.             or      bl,al                   ;Don't print leading zeros.
  1766.             cmp     bl,"0"                  ;The first non zero will
  1767.             jne     hex_1                   ;  change bl to non-zero.
  1768.             mov     al,20h
  1769. hex_1:
  1770.             push    bx
  1771.             mov     ah,0eh                  ;Write TTY
  1772.             mov     bl,12h
  1773.             call    vidint
  1774.             pop     bx
  1775.             loop    hex_loop2
  1776. hex_exit:
  1777.             ret
  1778. hex2asc         endp
  1779. ;-----------------------------------------------------------------------------
  1780. ; Extended boot data.
  1781. ;-----------------------------------------------------------------------------
  1782. boot_data_start =       $
  1783. boot_array      =       $
  1784. name1           db      "DOS Session         ",0
  1785. auto1           db      "AUTOEXECMB1"
  1786. config1         db      "CONFIG  MB1"
  1787. ostype1         db      1                       ;Index into op sys table
  1788.  
  1789. name2           db      NAME_LENGTH dup (80h),0
  1790.             db      "AUTOEXECMB2"
  1791.             db      "CONFIG  MB2"
  1792.             db      0
  1793.  
  1794. name3           db      NAME_LENGTH dup (80h),0
  1795.             db      "AUTOEXECMB3"
  1796.             db      "CONFIG  MB3"
  1797.             db      0
  1798.  
  1799. name4           db      NAME_LENGTH dup (80h),0
  1800.             db      "AUTOEXECMB4"
  1801.             db      "CONFIG  MB4"
  1802.             db      0
  1803. boot_array_end    =    $
  1804.  
  1805. opsys_table     =       $
  1806. os_name1        db      8 dup (80h),0           ;Name of operating system
  1807. os_ioname       db      "IO      SYS"           ;IO.SYS file name
  1808. os_comname      db      "MSDOS   SYS"           ;MSDOS.SYS file name
  1809. os_boottype    dw    0
  1810. os_name2        db      8 dup (80h),0
  1811.             db      "OS2LDR     "
  1812.             db      "OS2KRNL    "
  1813.         dw    0
  1814. os_name3        db      8 dup (80h),0
  1815.             db      "BIOS    SYS"
  1816.             db      "DOS     SYS"
  1817.             dw    0
  1818. os_name4        db      8 dup (80h),0
  1819.             db      "BIOS    SYS"
  1820.             db      "DOS     SYS"
  1821.               dw    0
  1822. opsys_table_end =       $
  1823. boot_data_end   =       $
  1824.  
  1825. normal_attr     db      COLOR_NORM
  1826. highlight_attr  db      COLOR_HIGH
  1827. screen_rows    db    0
  1828. last_timeout    dw      0
  1829. timeout_value   dw      0
  1830. no_DOS_flag    db    1            ;0 = No DOS resident.
  1831.  
  1832. number_buff     db      0,".",0
  1833.  
  1834. read_os_error    db    2,7,"Error Reading new DOS files",0
  1835. write_os_error    db    2,7,"Error Writing new DOS files",0
  1836. no_room_error    db    2,7,"Not enough room for new DOS files",0
  1837. boot_extend_err db      2,7,"Write error, Last choice booted.",0
  1838. change_os_msg    db    2,7,"Changing DOS System files",0
  1839.  
  1840. boot_os_msg    db    2,11,"Operating System: "
  1841. boot_os_msg1    db    NAME_LENGTH+1 dup (0)
  1842. boot_sess_msg    db    2,9,"Booting Session: "
  1843. boot_sess_msg1    db    9 dup (0)
  1844.  
  1845. timeout_str     db      41,23,"Time until default:",0
  1846. timetext1       db      61,23,"Indefinite",0
  1847. prompt_text     db      "Choice [ ]",0
  1848.  
  1849. autoexec_name   db      "AUTOEXECBAT"           ;Filenames to rename.
  1850. config_name     db      "CONFIG  SYS"
  1851.  
  1852. ibmbio_name    db    "IBMBIO  COM"        ;IBM DOS system file names
  1853. ibmcom_name    db    "IBMDOS  COM"
  1854. iosys_name    db    "IO      SYS"        ;MS DOS system file names
  1855. msdos_name    db    "MSDOS   SYS"
  1856.  
  1857. os_names_table    db    "MBOOTOSaBOT"        ;This array is used to hold
  1858.                   db    "MBOOTOSaSYS"        ;  the generated names of the
  1859.                   db    "MBOOTOSaCOM"        ;  DOS system  files.
  1860. ;
  1861. ; Boot Menu structure
  1862. ;
  1863. boot_menu       =       $
  1864. menu_struc      db      4                       ;Number of choices
  1865. selected        db      0                       ;Selected Item
  1866. prompt_loc      db      30,20                   ;Location of "Choices" prompt
  1867. timeout         dw      0                       ;Timeout value
  1868.             db      40,23                   ;Col, Row of Timeout string
  1869. firstitem       db      24,9                    ;Column, Row of menu item
  1870.             dw      offset name1            ;Offset of menu text
  1871.             db      24,11
  1872.             dw      offset name2
  1873.             db      24,13
  1874.             dw      offset name3
  1875.             db      24,15
  1876.             dw      offset name4
  1877.  
  1878. boxtext1        db      27,02,"PC Magazine",39,"s MultiBoot 1.1",0
  1879. boxtext2        db      26,03,"(c) 1991 Ziff Communications",0
  1880. boxtext3        db      32,04,"Douglas Boling",0
  1881. box1            db      10,01,201,186,186,186,200,0   ;"╔","║","║","║","╚"
  1882. box2            db      69,01,187,186,186,186,188,0   ;"╗","║","║","║","╝"
  1883.  
  1884. ;============================================================================
  1885. ;============================================================================
  1886. ; Start of installation code and data.
  1887. ;============================================================================
  1888. ;============================================================================
  1889.             even
  1890. install_start   =       $
  1891. inst_text1      db      "Session Title          AUTOEXEC File    "
  1892.             db      "CONFIG File      System",0
  1893.  
  1894. main_menu       db      8,0                     ;Number of choices, Selected
  1895.             db      30,22                   ;Location of "Choices" prompt
  1896.             dw      0                       ;Timeout value
  1897.             db      0,0                     ;Col, Row of Timeout string
  1898.             db      13,17                   ;Column, Row of menu item
  1899.             dw      offset add_entry        ;Offset of menu text
  1900.             db      13,18
  1901.             dw      offset delete_entry
  1902.             db      13,19
  1903.             dw      offset set_default
  1904.             db      13,20
  1905.             dw      offset add_osentry
  1906.             db      40,17
  1907.                 dw      offset install
  1908.             db      40,18
  1909.                 dw      offset remove
  1910.             db      40,19
  1911.             dw      offset exit_prog
  1912.             db      40,20
  1913.             dw      offset quit_prog
  1914.  
  1915. confirm_msg    db    20,16,"Do you wish to discard changes?",0
  1916.  
  1917. yes_text        db      "Yes",0
  1918. no_text         db      "No",0
  1919. yesno_menu      db      2,1                     ;Number of choices, Selected
  1920.             db      25,22                   ;Location of "Choices" prompt
  1921.             dw      0                       ;Timeout value
  1922.             db      0,0                     ;Col, Row of Timeout string
  1923.             db      25,18                   ;Column, Row of menu item
  1924.             dw      offset yes_text         ;Offset of menu text
  1925.             db      25,20
  1926.             dw      offset no_text
  1927.  
  1928. add_entry       db      "Add Session",0
  1929. delete_entry    db      "Delete Session",0
  1930. set_default     db      "Set Defaults",0
  1931. add_osentry     db      "Load Operating System",0
  1932. install         db      "Install MultiBoot",0
  1933. remove          db      "Remove MultiBoot",0
  1934. exit_prog       db      "Update and Exit MultiBoot",0
  1935. quit_prog       db      "Quit MultiBoot",0
  1936.  
  1937. return_text     db      "Update and Return",0
  1938. quit_text       db      "Return Without Changing",0
  1939. unused_text     db      "< Unused >",0
  1940. unused_text_end =       $
  1941.  
  1942. os2knl_name    db    "OS2KRNL    "
  1943. os2ldr_name    db    "OS2LDR     "
  1944. os2boot_aname    db    "C:\OS2\SYSTEM\BOOT.OS2",0
  1945.  
  1946. default_str     db      "Def.",0
  1947.  
  1948. command_table   dw      offset main_menu        ;Offset of menu for this table
  1949.                 dw      offset main_add         ;Command jump table
  1950.             dw      offset main_delete
  1951.             dw      offset main_defaults
  1952.             dw      offset main_osadd
  1953.             dw      offset main_install
  1954.             dw      offset main_remove
  1955.             dw      offset exit
  1956.             dw      offset quit
  1957.  
  1958. dos_version     dw      0
  1959. installed_flag  db      0                       ;Set if MultiBoot installed
  1960. changed_flag    db      0
  1961. local_changed   db      0
  1962. huge_flag    db    0            ;Set if target disk > 32M 
  1963. targ_sec_per_cluster dw 0
  1964.  
  1965. session_count    db    0            ;Number of used sessions
  1966. opsys_count    db    0            ;Number of operating systems
  1967.  
  1968. iosys_size    dw    0            ;Size of IO.SYS read
  1969. doscom_size    dw    0            ;Size of MSDOS.SYS read
  1970. opsys_ostype     dw    0            ;DOS File config 
  1971.  
  1972. databuff_ptr    dd      0                       ;Pointer to data buffer
  1973. databuff1_ptr   dd      0                       ;Pointer to second data buffer
  1974. crit_vec        dd    0            ;Saved critical error vector
  1975. ctlc_vec        dd    0            ;Saved control C vector
  1976. ctlc_stack    dw    0
  1977. ctlc_return    dw    0
  1978.  
  1979. drive_letter    db      "A"                     ;Target drive
  1980.  
  1981. installed_data    =    $
  1982.         db    3 dup (0)        ;Bytes for jump instruction
  1983. inst_data_ptr    dw    0            ;Offset of last boot data
  1984. inst_data_size    dw    0            ;Size of last boot data
  1985. inst_sess_ptr    dw    0            ;Offset of boot session table 
  1986. inst_sess_size    dw    0            ;Size of boot session table
  1987. inst_boot_ptr    dw    0            ;Offset of boot os table 
  1988. inst_boot_size    dw    0            ;Size of boot os table
  1989. inst_version    dw    0            ;Version of installed code
  1990. installed_data_end =    $    
  1991.  
  1992. key_buffer      db      64 dup (0)
  1993. temp_buff       db      64 dup (0)
  1994. filename_buff    db    20 dup (0)
  1995. temp        dw    0            ;Temp storage buffer
  1996.  
  1997.  
  1998. errmsg0         db      "Requires at least DOS 2.x$"
  1999. errmsg1         db      "This program cannot be run under OS/2$"
  2000. errmsg2         db      "Not enough memory for MultiBoot$"
  2001. errmsg3         db      "Too many open files$"
  2002. errmsg4         db      "Access to files denied$"
  2003. errmsg5         db      "Drive Letter not specified on command line$"
  2004. errmsg6         db      "Drive Letter invalid$"
  2005. errmsg7         db      "MultiBoot file MBOOT.SYS not found$"
  2006. errmsg8        db    "Not a bootable disk or unknown operating system$"
  2007. errmsg9        db    "MultiBoot must be run in 80 column mode$"
  2008. errmsg10    db    "Installed data is incompatible with this version$"
  2009. crmsg           db      13,10,"$"
  2010.  
  2011. error_msg_loc   dw      180ah                   ;Column, Row of error msgs
  2012.  
  2013. errmsg20        db      "Install error",0
  2014. errmsg21        db      "MultiBoot Already Installed",0
  2015. errmsg22        db      "Remove error",0
  2016. errmsg23        db      "MultiBoot Not Installed",0
  2017.  
  2018. ;-----------------------------------------------------------------------------
  2019. ; Prevent Abort,Retry,Ignore error msg with this dummy crit. error routine
  2020. ;-----------------------------------------------------------------------------
  2021. crit_error      proc    far
  2022.             mov     al,0                    ;Ignore critical error.
  2023.             iret
  2024. crit_error      endp
  2025.  
  2026. ;-----------------------------------------------------------------------------
  2027. ; Installation code.
  2028. ;-----------------------------------------------------------------------------
  2029. main            proc    near
  2030.             assume  ds:code
  2031.             cld                             ;Set string operations up
  2032.             mov     ah,30h                  ;Get DOS version, run only
  2033.             int     21h                     ;  if 2.0 or greater.
  2034.             xchg    al,ah                   ;Swap major, minor numbers
  2035.             mov     dx,offset errmsg0       ;Bad DOS version
  2036.             cmp     ah,2
  2037.             jb      jmp1_error_exit
  2038.             mov     dx,offset errmsg1       ;Program cannot be run in the
  2039.             cmp     ah,10                   ;  DOS box under OS/2.
  2040.             jae     jmp1_error_exit
  2041.             mov     dos_version,ax          ;Save version number
  2042.  
  2043.             mov     sp,offset end_of_code + 512     ;Move stack
  2044.             mov     ah,4ah                          ;Reduce memory alloc
  2045.             mov     bx,offset end_of_code + 527
  2046.             mov     cl,4
  2047.             shr     bx,cl
  2048.             int     21h
  2049.  
  2050.         int    12h            ;Get size of machine RAM 
  2051.         cmp    ax,384            ;Must be at least 384K to
  2052.             mov     dx,offset errmsg2       ;  use extended boot code.
  2053.             jb      jmp1_error_exit
  2054.  
  2055.             mov     ah,48h                  ;Allocate memory block for
  2056.             mov     bx,1000h                ;  data buffer.
  2057.             int     21h
  2058.             mov     dx,offset errmsg2       ;Not enough memory msg
  2059.             jc      jmp1_error_exit
  2060.             mov     word ptr databuff_ptr[2],ax     ;Save segment.
  2061.  
  2062.             mov     ah,48h                  ;Allocate memory block for
  2063.             mov     bx,1000h                ;  second data buffer.
  2064.             int     21h
  2065.             mov     dx,offset errmsg2       ;Not enough memory msg
  2066.             jc      jmp1_error_exit
  2067.             mov     word ptr databuff1_ptr[2],ax     ;Save segment.
  2068.         
  2069.         call    set_ctlc_vec        ;Setup Control-C routine
  2070.  
  2071.             mov     si,81h                  ;Point to command line tail
  2072.             xor     cx,cx
  2073.             or      cl,[si-1]               ;Get cmd tail length
  2074.             jne     main_2
  2075. main_1:
  2076.             mov     dx,offset errmsg5       ;Drive letter not specified.
  2077. jmp1_error_exit:
  2078.             jmp     error_exit
  2079. main_2:
  2080.             lodsb
  2081.             cmp     al,13                   ;See if end of line
  2082.             je      main_1                  ;If so, error.
  2083.             cmp     al," "
  2084.             ja      main_3
  2085.             loop    main_2
  2086.             jmp     short main_1
  2087. main_3:
  2088.         cmp    byte ptr [si],":"    ;Make sure drive letter 
  2089.         jne    main_1            ;  terminated by colon.
  2090.             and     al,0dfh                 ;Convert drive letter to
  2091.             cmp     al,"A"            ;  upper case.
  2092.             jb      main_1
  2093.             cmp     al,"Z"
  2094.             ja      main_1
  2095.             mov     drive_letter,al         ;Save drive letter
  2096.  
  2097.         call    set_crit_vec        ;Set crit vec to int routine
  2098.         call    huge_disk_check        ;See if target disk > 32 Meg
  2099.         call    reset_crit_vec        
  2100.         mov    dx,offset errmsg6
  2101.         jc    jmp1_error_exit
  2102.         je    main_not_huge
  2103.         inc    huge_flag        ;If so, set flag
  2104. main_not_huge:    
  2105.         mov    targ_sec_per_cluster,di
  2106.             call    check_os                ;See what system on target
  2107.          cmp    al,-1            ;  disk.
  2108.             mov     dx,offset errmsg6    ;See if error reading disk.
  2109.             je      jmp1_error_exit
  2110.  
  2111.         push    ax
  2112.         xor    al,al            ;Copy BIOS parameter block
  2113.         call    copy_bpb        ;  to boot rec data area.
  2114.         pop    ax
  2115.  
  2116.         cmp    al,3               ;See if MultiBoot installed
  2117.         je    main_installed
  2118.         mov    dx,offset errmsg8    ;If OS unknown or unbootable,
  2119.         cmp    al,2            ;  error.
  2120.         jae    jmp1_error_exit
  2121.  
  2122.         call    setup_multiboot        ;Not installed, setup.
  2123.         jmp    short main_5
  2124. main_installed:
  2125.             inc     installed_flag          ;Set installed flag
  2126.         call    get_inst_data        ;Read data from MBOOT.SYS
  2127.         jc    jmp1_error_exit
  2128. main_5:
  2129.         mov    cx,4
  2130.         mov    si,offset opsys_table    ;Count sessions and op systems
  2131.         mov    di,offset boot_array
  2132.         add    di,OSTYPE_OFFSET
  2133. main_count_loop:
  2134.         cmp    byte ptr [si],80h    ;If lead byte 80h, entry
  2135.         jae    main_6             ;  unused.
  2136.         inc    opsys_count        ;Inc number of op systems
  2137. main_6:
  2138.         cmp    byte ptr [di],0        ;Op Sys = 0, no session.
  2139.         je    main_7
  2140.         inc    session_count
  2141. main_7:
  2142.         add    di,NEXT_ENTRY        ;Point to next entries
  2143.         add    si,NEXT_OSENTRY
  2144.         loop    main_count_loop
  2145.  
  2146.         push    ds
  2147.         mov    ax,40h            ;Get number of screen rows
  2148.         mov    ds,ax
  2149.         mov    dl,[84h]        
  2150.         pop    ds
  2151.         mov    screen_rows,dl
  2152.  
  2153.         mov    ah,0fh            ;Read video mode
  2154.         call    vidint
  2155.         mov    dx,offset errmsg9    ;Must be in 80 column mode
  2156.         cmp    ah,80
  2157.         jb    error_exit
  2158.         cmp    al,0fh            ;Check for BW modes
  2159.         je    main_set_bw
  2160.         cmp    al,6
  2161.         jb    main_set_color
  2162.         cmp    al,7
  2163.         ja    main_set_color
  2164. main_set_bw:
  2165.         mov    normal_attr,BW_NORM    ;Use Black/White attributes
  2166.         mov    highlight_attr,BW_HIGH
  2167. main_set_color:
  2168.             call    write_box               ;Write copyright box
  2169. main_loop:
  2170.             mov     di,offset name1        ;Display current sessions
  2171.             call    disp_settings
  2172.         mov    local_changed,0
  2173.         mov    si,offset command_table    ;Display menu and jump to 
  2174.         mov    al,1            ;  proper routine. Default
  2175.         call    jump_menu        ;  to Add Session.
  2176.             pushf
  2177.             cmp     al,-1                   ;See if exit
  2178.             je      main_exit
  2179.             add     changed_flag,al         ;Set flag if mboot modified.
  2180.             call    scroll_half
  2181.             popf
  2182.             jnc     main_loop               ;If carry, print message
  2183.  
  2184.             call    write_error             ;Print error message
  2185.             jmp     short main_loop
  2186. error_exit:
  2187.             mov     ah,9                    ;Print error message
  2188.             int     21h
  2189.             mov     dx,offset crmsg
  2190.             mov     ah,9                    ;Insert carrage return
  2191.             int     21h
  2192.             mov     al,1
  2193.             jmp     short main_exit1
  2194. main_exit:
  2195.             popf                            ;Remove flags from stack
  2196.         mov    dx,0700h        ;Set cursor to Row 7 Column 0.
  2197.         call    set_cursor
  2198.             xor     ax,ax                   ;Clear return code
  2199. main_exit1:
  2200.             push    ax
  2201.             mov     ax,word ptr databuff_ptr[2]  ;Get segment.
  2202.             or      ax,ax
  2203.             je      main_exit2
  2204.             mov     es,ax
  2205.             mov     ah,49h                  ;Free data buffer
  2206.             int     21h
  2207. main_exit2:
  2208.             mov     ax,word ptr databuff1_ptr[2]  ;Get segment.
  2209.             or      ax,ax
  2210.             je      main_exit3
  2211.             mov     es,ax
  2212.             mov     ah,49h                  ;Free data buffer
  2213.             int     21h
  2214. main_exit3:
  2215.             pop     ax
  2216.             mov     ah,4ch
  2217.             int     21h
  2218. main            endp
  2219.  
  2220. ;--------------------------------------------------------------------
  2221. ; SETUP MULTIBOOT - Configures Multiboot if not installed.
  2222. ; Entry: AX - Operating system on target disk
  2223. ;        BX - DOS version
  2224. ;        CX - Consecutive clusters used by DOS files
  2225. ;--------------------------------------------------------------------
  2226. setup_multiboot    proc    near
  2227.         push    ax            ;Save operating system type
  2228.         push    bx            ;  and size.
  2229.         mov    opsys_clusters,cx
  2230.  
  2231.         mov    ah,2ch            ;Get system time for time
  2232.         int    21h            ;  stamp ID
  2233.         mov    word ptr time_stamp,cx
  2234.         mov    word ptr time_stamp[2],dx
  2235.         pop    cx            ;Get os config
  2236.         pop    ax            ;Get os type
  2237.  
  2238.             mov     bl,1                  ;The current os becomes the 
  2239.         call    copy_os_name        ;  default.
  2240.  
  2241.         mov    si,offset boot_extend_start  ;Copy installed data ptrs
  2242.         mov    di,offset installed_data
  2243.         mov    cx,offset installed_data_end - offset installed_data
  2244.         rep    movsb
  2245.  
  2246.         cmp    ah,1            ;See if OS/2 installed
  2247.         jne    setup_multiboot_1
  2248.         mov    dx,offset os2boot_aname    ;Yes, look for BOOT.OS2
  2249.         mov    cl,drive_letter
  2250.         mov    byte ptr os2boot_aname,cl
  2251.         push    es
  2252.         les    si,databuff_ptr        ;Read OS/2 boot record file.
  2253.         call    read_file        
  2254.         pop    es
  2255.         jc    setup_multiboot_1
  2256.         mov    bl,2
  2257.         mov    cx,100h            ;OS type = OS/2
  2258.         call    copy_os_name        ;Copy OEM name.
  2259. setup_multiboot_1:
  2260.         mov    bl,1            ;Verify default session
  2261.         call    get_entry        ;  filenames are not used.
  2262.         mov    cx,8
  2263. setup_multiboot_2:
  2264.         lea    si,[bx+AUTO_OFFSET]    ;Search for the filenames used
  2265.         call    find_first        ;  in the default session.  If
  2266.         jnc    setup_multiboot_3    ;  used, rename by changing 
  2267.         lea    si,[bx+CONFIG_OFFSET]    ;  the extension.
  2268.         call    find_first
  2269.         jc    setup_exit
  2270. setup_multiboot_3:
  2271.         inc    byte ptr [bx+AUTO_OFFSET+10]
  2272.         inc    byte ptr [bx+CONFIG_OFFSET+10]
  2273.         loop    setup_multiboot_2        ;If all filenames used
  2274.         mov    byte ptr [bx+OSTYPE_OFFSET],0    ;  delete default.
  2275. setup_exit:
  2276.         ret
  2277. setup_multiboot    endp
  2278.  
  2279. ;--------------------------------------------------------------------
  2280. ; GET INST DATA - Reads the configutation data from MBOOT.SYS
  2281. ; Exit:  CF - Set if error
  2282. ;        DX - Offset of error message.
  2283. ;--------------------------------------------------------------------
  2284. get_inst_data    proc    near
  2285.             mov     si,offset mboot_name    ;Open the MBOOT.SYS file to
  2286.             call    make_filename           ;  read the boot information.
  2287.         xor    cx,cx
  2288.         call    set_attributes        ;Clear the file attributes.
  2289.             mov     ax,3d02h
  2290.             int     21h
  2291.         jc    get_inst_file_error
  2292.  
  2293.         mov    bx,ax            ;Copy file handle
  2294.         mov    ah,3fh            ;Read ptr to boot table
  2295.         mov    dx,offset installed_data
  2296.         mov    cx,offset installed_data_end - offset installed_data
  2297.         int    21h
  2298.         jc    get_inst_file_error
  2299.  
  2300.         mov    dx,offset errmsg10    ;See if installed data    
  2301.         cmp    inst_version,20h    ;  compatible    
  2302.         jae    get_inst_data_error
  2303.  
  2304.         mov    ax,4200h        ;Move file ptr 
  2305.         mov    dx,inst_data_ptr    
  2306.         xor    cx,cx
  2307.         int    21h
  2308.         jc    get_inst_file_error
  2309.             mov     ah,3fh                  ;Read default session data
  2310.             mov     dx,offset boot_data1
  2311.             mov     cx,inst_data_size
  2312.             int     21h
  2313.             jnc     get_inst_data_1
  2314. get_inst_file_error:
  2315.             mov     dx,offset errmsg7       ;Boot file error.
  2316.             cmp     ax,2                    ;See if file not found
  2317.             je      get_inst_data_error     ;Yes, error
  2318.             mov     dx,offset errmsg3       ;See if too many files opened
  2319.             cmp     ax,4
  2320.             je      get_inst_data_error
  2321.             mov     dx,offset errmsg4       ;Assume access denied
  2322. get_inst_data_error:
  2323.         stc
  2324.             jmp     short get_inst_data_exit
  2325. get_inst_data_1:
  2326.         mov    ax,4200h        ;Move file ptr to session table
  2327.         mov    dx,inst_sess_ptr    
  2328.         xor    cx,cx
  2329.         int    21h
  2330.         jc    get_inst_file_error
  2331.             mov     ah,3fh                  ;Read boot session data 
  2332.             mov     dx,offset boot_array
  2333.             mov     cx,inst_sess_size
  2334.             int     21h
  2335.         jc    get_inst_file_error
  2336.  
  2337.         mov    ax,4200h        ;Move file ptr to session table
  2338.         mov    dx,inst_boot_ptr    
  2339.         xor    cx,cx
  2340.         int    21h
  2341.         jc    get_inst_file_error
  2342.             mov     ah,3fh                  ;Read boot session data 
  2343.             mov     dx,offset opsys_table
  2344.             mov     cx,inst_boot_size
  2345.             int     21h
  2346.         jc    get_inst_file_error
  2347.  
  2348.             mov     ah,3eh                  ;Close file
  2349.             int     21h
  2350.             mov     si,offset mboot_name    ;Set MBOOT.SYS file attributes
  2351.             call    make_filename           ;  to hidden, system, and  
  2352.         mov    cx,SYSFILE_ATTR        ;  read only.
  2353.         call    set_attributes        
  2354.         jc    get_inst_file_error
  2355. get_inst_data_exit:
  2356.         ret
  2357. get_inst_data    endp
  2358.  
  2359. ;--------------------------------------------------------------------
  2360. ; MAIN ADD - Displays the Add Session submenu.
  2361. ;--------------------------------------------------------------------
  2362. local_add1      db      NEXT_ENTRY dup (0)      ;Local copy of boot table
  2363. local_add2      db      NEXT_ENTRY dup (0)
  2364. local_add3      db      NEXT_ENTRY dup (0)
  2365. local_add4      db      NEXT_ENTRY dup (0)
  2366. local_add_end   =       $
  2367. local_add_count    db    0
  2368.  
  2369. local_selection dw      0                       ;Current selected session
  2370. local_add_menu  =       $
  2371.             db      4                       ;Number of choices
  2372. add_select      db      0                       ;Selected Item
  2373.             db      30,20                   ;Location of "Choices" prompt
  2374.             dw      0                       ;Timeout value
  2375.             db      0, 0                    ;Col, Row of Timeout string
  2376.             db      24,9                    ;Column, Row of menu item
  2377.             dw      offset local_add1       ;Offset of menu text
  2378.             db      24,11
  2379.             dw      offset local_add2
  2380.             db      24,13
  2381.             dw      offset local_add3
  2382.             db      24,15
  2383.             dw      offset local_add4
  2384.  
  2385. add_str2        db      20,7
  2386. add_select_str1 db      "Current Sessions",0
  2387. add_add_text    db      "Add Session",0
  2388. add_rename_text db      "Rename Session",0
  2389.  
  2390. add_str4        db      05,14,"Enter the title of the session:",0
  2391. add_str7        db      15,16,"Is this correct?",0
  2392.  
  2393. add_str_msg1    db      10,22,"Press Ctrl-Break to return to Add Menu",0
  2394. add_str_err1    db      "No Sessions Added",0
  2395. add_str_err2    db      "No free sessions, delete a session first",0
  2396.  
  2397. add_table    dw    offset add_menu
  2398.         dw    offset add_add_sess
  2399.         dw    offset add_rename
  2400.         dw    offset add_exit
  2401.         dw    offset add_quit
  2402.  
  2403. add_menu        db      4,0                     ;Number of choices, Selected
  2404.             db      30,22                   ;Location of "Choices" prompt
  2405.             dw      0                       ;Timeout value
  2406.             db      0,0                     ;Col, Row of Timeout string
  2407.             db      25,17                   ;Column, Row of menu item
  2408.             dw      offset add_add_text     ;Offset of menu text
  2409.             db      25,18
  2410.             dw      offset add_rename_text 
  2411.             db      25,19
  2412.             dw      offset return_text
  2413.             db      25,20
  2414.             dw      offset quit_text
  2415.  
  2416. main_add        proc    near
  2417.             assume  cs:code,ds:code
  2418.             mov     di,offset local_add1    ;Copy boot array
  2419.             mov     si,offset boot_array
  2420.             mov     cx,4                    ;4 Entries.
  2421. main_add_0:
  2422.              push    cx                      ;Copy the contents of the
  2423.              mov     cx,NEXT_ENTRY           ;  marked unused, replace
  2424.         mov    bx,di
  2425.              rep     movsb                   
  2426.              cmp     byte ptr [bx+OSTYPE_OFFSET],0 ;See if session unused.
  2427.              jne     main_add_02
  2428.              mov     byte ptr [bx+AUTO_OFFSET],0     ;If unused, clear
  2429.              mov     byte ptr [bx+CONFIG_OFFSET],0   ;  filename entries
  2430.         mov    byte ptr [bx],80h
  2431. main_add_02:
  2432.              pop     cx
  2433.              loop    main_add_0
  2434.         mov    al,session_count    ;Copy session count
  2435.         mov    local_add_count,al
  2436. main_add_1:
  2437.             mov     di,offset local_add1    ;Display current sessions.
  2438.             call    disp_settings
  2439.  
  2440.             mov     si,offset add_table    ;Display the add menu
  2441.             mov     al,1
  2442.             call    jump_menu        ;Call submenu routines
  2443.         pushf                ;Save carry flag
  2444.         pop    bx
  2445.         cmp    al,-1
  2446.         jne    main_add_1
  2447.             mov     al,local_changed        ;Indicate if changes made.
  2448.         push    bx            ;Restore carry flag if needed
  2449.         popf
  2450.         ret
  2451.  
  2452. ;--------------------------------------------------------------------
  2453. ; ADD ADD SESSION - adds an entry to the boot table.
  2454. ;--------------------------------------------------------------------
  2455. add_add_sess    proc    near
  2456.             call    scroll_half             
  2457.         xor    bx,bx
  2458.         mov    bl,local_add_count      ;Get number of sessions.
  2459.         cmp    bl,4            ;See if too many
  2460.         jb    add_add_sess_1
  2461.         mov    si,offset add_str_err2
  2462.         call    write_error        ;Print error message
  2463.         jmp    add_add_sess_exit
  2464. add_add_sess_1:
  2465.         mov    cx,4
  2466.         xor    bx,bx            ;Find first free boot table        
  2467.         mov    si,offset local_add1    ;  entry.
  2468. add_add_sess_11:
  2469.         inc    bx
  2470.         cmp    byte ptr [si+OSTYPE_OFFSET],0
  2471.         je    add_add_sess_12        
  2472.         add    si,NEXT_ENTRY
  2473.         loop    add_add_sess_11
  2474. add_add_sess_12:
  2475.         call    get_sess_name        ;Get session name
  2476.         jnc    add_add_sess_13
  2477. jmp_add_add_sess_5:
  2478.         jmp    add_add_sess_5
  2479. add_add_sess_13:
  2480.         mov    local_selection,bp
  2481.             mov     si,offset autoexec_name ;Point to AUTOEXEC.BAT name
  2482.             call    add_file
  2483.         jc    jmp_add_add_sess_5
  2484.             mov     di,local_selection      ;Copy AUTOEXEC filename to
  2485.             add     di,AUTO_OFFSET          ;  local array.
  2486.             mov     cx,12
  2487.             rep     movsb
  2488.  
  2489.             mov     si,offset config_name   ;Point to CONFIG.SYS name
  2490.             call    add_file
  2491.         jc    add_add_sess_5
  2492.             mov     di,local_selection      ;Copy CONFIG filename to
  2493.             add     di,CONFIG_OFFSET        ;  local array.
  2494.             mov     cx,12
  2495.             rep     movsb
  2496.  
  2497.             mov     dh,10
  2498.             call    clear_line
  2499.             mov     di,local_selection      ;Write session data to screen
  2500.             call    disp_session
  2501.  
  2502.             mov     dh,14
  2503.             call    clear_line
  2504. add_add_sess_2:
  2505.         mov    bl,1            ;Assume only one OS.
  2506.         cmp    opsys_count,1
  2507.         je    add_add_sess_3         ;If only one OS, don't display
  2508.         call    get_ostype         ;  OS menu.
  2509.         or    bl,bl
  2510.         je    add_add_sess_2        ;Must select an os.
  2511. add_add_sess_3:
  2512.             mov     di,local_selection      ;Set OS type
  2513.             add     di,OSTYPE_OFFSET
  2514.             mov     byte ptr [di],bl
  2515.  
  2516.             mov     dh,10
  2517.             call    clear_line
  2518.             mov     di,local_selection      ;Write session data to screen
  2519.             call    disp_session
  2520.  
  2521.             mov     al,1
  2522.             mov     si,offset add_str7      ;Ask user to verify changes.
  2523.             call    msg_box
  2524.             cmp     bl,1                    ;See if Yes.
  2525.             je      add_add_sess_4
  2526.         mov    di,local_selection        ;If no, clear entries
  2527.         mov    byte ptr [di],80h        ;  and return to 
  2528.                mov     byte ptr [di+AUTO_OFFSET],0     ;  add menu.
  2529.              mov     byte ptr [di+CONFIG_OFFSET],0   
  2530.              mov     byte ptr [di+OSTYPE_OFFSET],0   
  2531.             jmp     short add_add_sess_exit
  2532. add_add_sess_4:
  2533.             mov     local_changed,1         ;Set changes flag
  2534.         inc    local_add_count      ;Inc number of sessions
  2535. add_add_sess_5:
  2536.             call    scroll_half
  2537. add_add_sess_exit:
  2538.         xor    al,al            
  2539.             ret
  2540. add_add_sess    endp
  2541.  
  2542. ;--------------------------------------------------------------------
  2543. ; ADD RENAME SESSION - Renames a session.
  2544. ;--------------------------------------------------------------------
  2545. add_rename    proc    near
  2546.         mov    bp,offset local_add_menu
  2547.         xor    ax,ax
  2548.         call    get_session_2        ;Ask for a session 
  2549.             jc      add_rename_session_exit
  2550.  
  2551.             or      bx,bx            ;See if no choice
  2552.             jz      add_rename_session_exit
  2553.  
  2554.         call    get_sess_name        ;Ask for a session name
  2555.         jc    add_rename_session_exit
  2556.         mov    local_changed,1
  2557. add_rename_session_exit:
  2558.             call    scroll_half
  2559.         xor    al,al            ;Clear exit flag
  2560.             ret
  2561. add_rename    endp
  2562. ;--------------------------------------------------------------------
  2563. ; ADD EXIT - Copies the local data to the main boot table then sets
  2564. ;             the exit flag
  2565. ;--------------------------------------------------------------------
  2566. add_exit    proc    near
  2567.             mov     bx,offset local_add1
  2568.             mov     dx,offset boot_array
  2569.             mov     cx,4                    ;4 Entries.
  2570. main_add_5:
  2571.             push    cx                      ;Copy only entrys used.
  2572.             mov     si,bx
  2573.             mov     di,dx
  2574.             cmp     byte ptr [bx+OSTYPE_OFFSET],0   ;See of entry used.
  2575.             je      main_add_6
  2576.             mov     cx,NEXT_ENTRY
  2577.             rep     movsb
  2578. main_add_6:
  2579.             add     dx,NEXT_ENTRY
  2580.             add     bx,NEXT_ENTRY
  2581.             pop     cx
  2582.             loop    main_add_5
  2583.         mov    al,local_add_count    ;Copy new number of sessions
  2584.         mov    session_count,al
  2585.             mov    al,-1            ;Set exit flag
  2586.         ret
  2587. add_exit    endp
  2588.     
  2589. ;--------------------------------------------------------------------
  2590. ; ADD QUIT - Querys user for verification then returns exit flag
  2591. ;--------------------------------------------------------------------
  2592. add_quit    proc    near    
  2593.         xor    al,al
  2594.             cmp     local_changed,0        ;See if any changes made
  2595.             je      add_quit_1
  2596.             call    confirm_quit
  2597.         jne    add_quit_exit
  2598.             mov     si,offset add_str_err1  ;No changes message.
  2599.             mov     local_changed,0         ;Clear changes flag
  2600. add_quit_1:
  2601.         mov    al,-1            ;Set exit flag
  2602. add_quit_exit:
  2603.         ret
  2604. add_quit    endp    
  2605. main_add        endp
  2606.  
  2607. ;--------------------------------------------------------------------
  2608. ; MAIN DELETE - Deletes an entry to the boot table.
  2609. ;--------------------------------------------------------------------
  2610. local_delete    dw      4 dup (0)               ;Delete flag for each session
  2611.  
  2612. delete_str2     db      20,07
  2613. del_select      db      "Select Session to Delete",0
  2614. delete_str3     db      15,11,"Do you want to delete the CONFIG.SYS"
  2615.             db      " and AUTOEXEC.BAT",0
  2616. delete_str4     db      15,12,"files for this Session?",0
  2617.  
  2618. delete_err1    db    "Can",39,"t delete active session.",0
  2619.  
  2620. tbdel_text      db      "To Be Deleted ->",0
  2621.  
  2622. delete_table    dw    offset delete_menu
  2623.         dw    offset delete_delete_session
  2624.         dw    offset delete_exit
  2625.         dw    offset add_quit
  2626.  
  2627. delete_menu     db      3,0                     ;Number of choices, Selected
  2628.             db      30,22                   ;Location of "Choices" prompt
  2629.             dw      0                       ;Timeout value
  2630.             db      0,0                     ;Col, Row of Timeout string
  2631.             db      25,18                   ;Column, Row of menu item
  2632.             dw      offset del_select       ;Offset of menu text
  2633.             db      25,19
  2634.             dw      offset return_text
  2635.             db      25,20
  2636.             dw      offset quit_text
  2637.  
  2638. main_delete     proc    near
  2639.             assume  cs:code,ds:code
  2640.             xor     ax,ax                   ;Clear local delete flags.
  2641.             mov     di,offset local_delete
  2642.             stosw
  2643.             stosw
  2644.             stosw
  2645.             stosw
  2646.         xor    bx,bx
  2647. main_delete_1:    
  2648.         push    bx
  2649.         popf
  2650.         jnc    main_delete_2
  2651.         call    write_error
  2652. main_delete_2:    
  2653.             mov     bp,offset boot_menu    ;Display sessions
  2654.         call    write_menu        ;  in menu form.
  2655.             mov     cx,4
  2656.             mov     dx,word ptr firstitem   ;Starting cursor loc from
  2657.             mov     dl,5                    ;  boot menu structure.
  2658.             mov     si,offset local_delete
  2659. main_delete_3:
  2660.             lodsw
  2661.             or      al,al                   ;See if session to be deleted
  2662.             je      main_delete_4           ;No, skip
  2663.             push    si
  2664.             mov     si,offset tbdel_text
  2665.             call    write_line_at
  2666.             pop     si
  2667. main_delete_4:
  2668.             inc     dh                      ;Move to next cursor location
  2669.             inc     dh
  2670.             loop    main_delete_3
  2671. ;Display delete menu.
  2672.             mov     si,offset delete_table    ;Display the delete menu
  2673.             mov     al,1
  2674.             call    jump_menu
  2675.         pushf                ;Save carry flag
  2676.         pop    bx
  2677.         cmp    al,-1            ;See if exit flag set
  2678.         jne    main_delete_1
  2679.             mov     al,local_changed        ;Indicate if changes made.
  2680.         push    bx            ;Restore carry flag if needed
  2681.         popf
  2682.         ret        
  2683.  
  2684. ;--------------------------------------------------------------------
  2685. ; DELETE DELETE SESSION - Querys the user for the session to delete 
  2686. ;--------------------------------------------------------------------
  2687. delete_delete_session    proc    near
  2688.             mov     al,0                    ;Get session to delete.
  2689.             call    get_session
  2690.             jc      delete_delete_exit
  2691.         cmp    bx,last_choice        ;Make sure not deleting 
  2692.         jne    delete_delete_0        ;  current session.
  2693.         mov    si,offset delete_err1
  2694.         xor    al,al
  2695.         stc    
  2696.         jmp    short delete_delete_exit1
  2697. delete_delete_0:
  2698.             push    bx
  2699.             call    scroll_half             ;See if we need to delete the
  2700.             mov     si,offset delete_str3   ;  CONFIG.SYS and AUTOEXEC.BAT
  2701.             call    write_linenorm          ;  files.
  2702.             mov     si,offset delete_str4
  2703.             mov     al,2
  2704.             call    msg_box
  2705.             mov     ah,bl                   ;Copy yes no answer
  2706.             pop     bx                      ;Restore selection to delete
  2707.             jnc     delete_delete_1
  2708.             mov     ah,2                    ;If <esc> force No reply.
  2709. delete_delete_1:
  2710.             dec     ah
  2711.             dec     bx
  2712.             shl     bx,1
  2713.             mov     al,1
  2714.             mov     [bx+local_delete],ax    ;Save delete flags for this
  2715.             call    scroll_half             ;  selection.
  2716. delete_delete_exit:
  2717.         xor    al,al            ;Clear exit flag
  2718. delete_delete_exit1:
  2719.         ret
  2720. delete_delete_session     endp
  2721.  
  2722. ;--------------------------------------------------------------------
  2723. ; DELETE EXIT - Performs the delete of sessions requested then sets
  2724. ;               the error flag.
  2725. ;--------------------------------------------------------------------
  2726. delete_exit    proc    near
  2727.             mov     cx,4
  2728.             mov     si,offset local_delete  ;Set ptr to delete selections
  2729.             mov     di,offset name1         ;Point to 1st session title
  2730. delete_exit_1:
  2731.             lodsw                           ;Get flag for selection
  2732.             or      al,al                   ;Delete entry?
  2733.             je      delete_exit_3
  2734.             mov     byte ptr [di+OSTYPE_OFFSET],0 ;Delete entry in list
  2735.             or      byte ptr [di],80h
  2736.         dec    session_count
  2737.             mov     local_changed,1         ;Set changed flag
  2738.             mov     dl,5
  2739.             sub     dl,cl
  2740.             cmp     dl,boot_default         ;If entry just deleted was
  2741.             jne     delete_exit_2           ;  the default, remove default.
  2742.             mov     boot_default,0
  2743. delete_exit_2:
  2744.             or      ah,ah                   ;Should the AUTOEXEC and
  2745.             jne     delete_exit_3           ;  CONFIG files be deleted?
  2746.             push    si
  2747.             lea     si,[di+AUTO_OFFSET]     ;Yes, delete files
  2748.             call    delete_file
  2749.             lea     si,[di+CONFIG_OFFSET]
  2750.             call    delete_file
  2751.             pop     si
  2752. delete_exit_3:
  2753.             add     di,NEXT_ENTRY           ;Point to next session title
  2754.             loop    delete_exit_1
  2755.         mov    al,-1            ;Set exit flag
  2756.         ret
  2757. delete_exit    endp
  2758. main_delete     endp
  2759.  
  2760. ;--------------------------------------------------------------------
  2761. ; INST OSADD - Adds an operating system to the disk.
  2762. ;--------------------------------------------------------------------
  2763. osadd_str0      db      25,07,"Current Operating Systems",0
  2764. osadd_str1      db      10,08,"Insert Diskette with new DOS system"
  2765.             db      " into Drive A:",0
  2766. osadd_str2      db      10,10,"Press any key when Diskette inserted.",0
  2767. osadd_str3      db      10,08,"Insert Target diskette into Drive A:",0
  2768. osadd_str4      db      10,08,"Current Operating System name: "
  2769. osadd_namestr    db    9 dup (0)
  2770. osadd_str5      db      10,10,"New Operating System name:",0
  2771. osadd_str6      db      10,10,"Reading DOS System files",0
  2772. osadd_str7      db      10,10,"Writing DOS System files",0
  2773. osadd_dos5    db    15,16,"Are you installing DOS 5.0 or greater?",0
  2774. osadd_dos4    db    15,16,"Are you installing DOS 4.0 or greater?",0
  2775. osadd_dos3    db    15,16,"Are you installing DOS 3.0 or greater?",0
  2776.  
  2777. osadd_err1    db    "Only four operating systems can be added",0
  2778. osadd_err2    db    "Can",39,"t delete last operating system",0
  2779. osadd_err3    db    "Diskette is not a bootable DOS diskette",0
  2780. osadd_err4    db    "MultiBoot installed on diskette",0
  2781. osadd_err5    db    "OS/2 cannot be installed from diskette",0
  2782. osadd_err6    db    "Error writing DOS System files to the disk",0
  2783. osadd_err7    db    "Operating system used by a session. Delete session "
  2784.         db    "first",0
  2785. osadd_err8    db    "New DOS system files larger than original DOS system"
  2786.         db    " files",0
  2787. osadd_err9    db    "Target disk not original MultiBoot disk."
  2788.         db    "  DOS system not loaded",0
  2789. osadd_err10    db    "MultiBoot must be installed before adding"
  2790.         db    " an Operating System",0
  2791. osadd_err11    db    "Error updating MBOOT.SYS file",0
  2792.  
  2793. osa_addos_text    db    "Add an operating system",0
  2794. osa_delos_text    db    "Delete an operating system",0
  2795. osa_renos_text    db    "Rename an operating system",0
  2796.  
  2797. osadd_table    dw    offset osadd_menu
  2798.         dw    offset osadd_add_opsys
  2799.         dw    offset osadd_del_opsys
  2800.         dw    offset osadd_ren_opsys
  2801.         dw    offset osadd_exit
  2802.  
  2803. osadd_menu      db      4,0                     ;Number of choices, Selected
  2804.             db      30,22                   ;Location of "Choices" prompt
  2805.             dw      0                       ;Timeout value
  2806.             db      0,0                     ;Col, Row of Timeout string
  2807.             db      25,17                   ;Column, Row of menu item
  2808.             dw      offset osa_addos_text   ;Offset of menu text
  2809.             db      25,18
  2810.             dw      offset osa_delos_text
  2811.             db      25,19
  2812.             dw      offset osa_renos_text
  2813.             db      25,20
  2814.             dw      offset return_text
  2815.  
  2816. main_osadd      proc    near
  2817.             assume  cs:code,ds:code
  2818.         xor    bx,bx            ;First time, no error.
  2819. main_osadd_1:    
  2820.         push    bx            ;Check for carry indicating
  2821.         popf                ;  an error message display
  2822.         jc    main_osadd_2
  2823.         call    scroll_half        ;Clear screen
  2824. main_osadd_2:
  2825.             mov     si,offset osadd_str0    ;Display current op systems
  2826.             call    write_linenorm        
  2827.  
  2828.         xor    cx,cx
  2829.         mov    cl,opsys_count        ;Four operating systems
  2830.         mov    dx,0920h        
  2831.         mov    si,offset opsys_table    ;Point to the opsys table
  2832. main_osadd_3:    
  2833.         push    si            
  2834.         call    write_line_at        
  2835.         pop    si
  2836.         add    si,NEXT_OSENTRY
  2837.         add    dh,2
  2838.         loop    main_osadd_3
  2839. ;Display os add menu.
  2840.             mov     si,offset osadd_table    ;Display the op sys add menu
  2841.             mov     al,1
  2842.             call    jump_menu
  2843.         pushf                ;Save carry flag
  2844.         pop    bx
  2845.         cmp    al,-1            ;See if exit flag set
  2846.         jne    main_osadd_1
  2847.             xor     ax,ax            ;Indicate if changes made.
  2848.         push    bx            ;Restore carry flag if needed
  2849.         popf
  2850.         ret        
  2851.  
  2852. ;--------------------------------------------------------------------
  2853. ; OSADD ADD OPSYS - Adds an operating system to the disk.
  2854. ;--------------------------------------------------------------------
  2855. osadd_add_opsys proc    near
  2856.         mov    si,offset osadd_err1    ;Only room for four operating
  2857.         cmp    opsys_count,4        ;  systems.
  2858.         jae    jmp_osadd_error
  2859.  
  2860.         mov    si,offset osadd_err10    ;Must be installed message
  2861.         cmp    installed_flag,0    
  2862.         je    jmp_osadd_error
  2863.  
  2864.             mov     si,offset osadd_str1    ;Prompt user for opsys 
  2865.             call    write_linenorm        ;  diskette.
  2866.             mov     si,offset osadd_str2
  2867.             call    write_linenorm
  2868.  
  2869.         call    fetch_key        ;Read a key from the keyboard
  2870.  
  2871.         call    clear_msg         ;Clear message off screen
  2872.             mov     si,offset osadd_str6    ;Reading files message
  2873.             call    write_linenorm
  2874.         
  2875.         mov    al,"A"            ;Set disk A
  2876.         call    get_opsys         ;Read operating sys from disk
  2877.  
  2878.         mov    ah,0             ;Ignore OS/2 flag
  2879.         push    ax            ;Save os type
  2880.         push    cx
  2881.         push    dx
  2882.         pushf                ;Save error flag
  2883.         cmp    drive_letter,"A"    
  2884.         jne    osadd_add_3
  2885.             mov     si,offset osadd_str3    ;Prompt user for target
  2886.             call    write_linenorm        ;  diskette.
  2887.             mov     si,offset osadd_str2
  2888.             call    write_linenorm
  2889.  
  2890.         call    fetch_key        ;Read a key from the keyboard
  2891. osadd_add_3:
  2892.         call    clear_msg         ;Clear message off screen
  2893.         popf                ;Restore error flags
  2894.         pop    dx            ;Restore IO.SYS size
  2895.         pop    cx            ;Restore DOS system size
  2896.         pop    ax            ;Restore os type
  2897.     
  2898.         jnc    osadd_add_11
  2899.         mov    si,offset osadd_err8
  2900.         cmp    al,7            ;See if Op sys too big
  2901.         je    jmp_osadd_error
  2902.         mov    si,offset osadd_err4
  2903.         cmp    al,3            ;See if Multiboot diskette 
  2904.         je     jmp_osadd_error
  2905.         mov    si,offset osadd_err5
  2906.         cmp    al,2            ;See if OS/2 diskette
  2907.         je    jmp_osadd_error
  2908.         mov    si,offset osadd_err3
  2909.         cmp    al,1            ;See if diskette is bootable
  2910.         jbe    osadd_add_11
  2911. jmp_osadd_error:
  2912.         jmp    osadd_error
  2913. osadd_add_11:
  2914.         call    chk_mboot_disk        ;See that proper disk is in
  2915.             mov     si,offset osadd_err9    ;  drive.
  2916.         jc    jmp_osadd_error
  2917.  
  2918.         cmp    opsys_ostype,50h
  2919.         je    osadd_add_14    
  2920.         mov    si,offset osadd_dos5    ;Ask user if installing DOS 5
  2921.         mov    di,50h
  2922.         cmp    opsys_clusters,0
  2923.         je    osadd_add_12
  2924.  
  2925.         mov    si,offset osadd_dos4    ;Ask user if installing DOS 4
  2926.         mov    di,40h
  2927.         cmp    huge_flag,0        ;If disk > 32 Meg, ask for 
  2928.         jne    osadd_add_12        ;   DOS 4
  2929.         cmp    dx,opsys_clusters
  2930.         ja    osadd_add_12
  2931.         mov    si,offset osadd_dos3    ;Ask user if installing DOS 3
  2932.         mov    di,30h
  2933.         cmp    cx,opsys_clusters
  2934.         jb    osadd_add_14
  2935. osadd_add_12:
  2936.         push    ax
  2937.         push    di
  2938.         mov    al,1            ;Set default to Yes
  2939.         call    msg_box
  2940.         pop    di
  2941.         pop    ax
  2942.         cmp    bl,1            ;See if answer Yes
  2943.         mov    si,offset osadd_err8
  2944.         jne    jmp_osadd_error
  2945.         mov    opsys_ostype,di        ;Save new opsys type
  2946. osadd_add_14:
  2947.         push    ax            ;Save os type
  2948.             mov     si,offset osadd_str7    ;Writing files message
  2949.             call    write_linenorm
  2950.         inc    opsys_count        ;Inc count of operating systems
  2951.         xor    bx,bx
  2952.         mov    bl,opsys_count        ;Get slot to place names
  2953.  
  2954.         mov    al,1              ;Copy BIOS param blk to  
  2955.         call    copy_bpb        ;  new boot record.
  2956.         pop    ax               ;Get opsys type
  2957.         mov    bp,ax
  2958.         call    put_opsys
  2959.  
  2960.         mov    si,offset osadd_err6    ;Error writing files
  2961.         jc    jmp_osadd_error
  2962.  
  2963.         mov    cx,4
  2964.         mov    si,offset opsys_table    ;Find first empty entry in
  2965.         xor    bx,bx            ;  the op sys table.
  2966. osadd_add_32:
  2967.         inc    bl
  2968.         cmp    byte ptr [si],80h
  2969.         jae    osadd_add_33
  2970.         add    si,NEXT_OSENTRY
  2971.         loop    osadd_add_32
  2972. osadd_add_33:
  2973.         mov    cx,opsys_ostype        ;Get DOS file config
  2974.         mov     ax,bp               ;Copy the op sys name from 
  2975.         call    copy_os_name        ;  the OEM name in the boot.
  2976.         xor    ax,ax
  2977.         mov    local_changed,1
  2978.         ret
  2979. osadd_error:
  2980.         call    scroll_half        ;Clear screen
  2981.         call    write_error        ;Print error message
  2982.         stc
  2983.         ret
  2984. osadd_add_opsys    endp
  2985.  
  2986. ;--------------------------------------------------------------------
  2987. ; OSADD DEL OPSYS - Deletes an operating system from the disk.
  2988. ;--------------------------------------------------------------------
  2989. osadd_del_opsys    proc    near
  2990.         mov    si,offset osadd_err2    ;Delete.  Don't delete active
  2991.         cmp    opsys_count,1        ;  OS files.
  2992.         jbe    osadd_error
  2993.  
  2994.         call    get_ostype        ;Query user for opsys
  2995.         mov    cx,4            
  2996.         mov    si,offset osadd_err7    ;Check to see if os is in use
  2997.         mov    di,offset ostype1
  2998. osadd_del_opsys_1:
  2999.         cmp    [di],bl
  3000.         je    osadd_error
  3001.         add    di,NEXT_ENTRY    
  3002.         loop    osadd_del_opsys_1
  3003.  
  3004.         call    delete_opsys        ;Erase op sys files
  3005. osadd_del_opsys_exit:
  3006.         dec    opsys_count
  3007.         xor    ax,ax
  3008.         mov    local_changed,1
  3009.         ret
  3010. osadd_del_opsys    endp
  3011.  
  3012. ;--------------------------------------------------------------------
  3013. ; OSADD REN OPSYS - Renames an operating system on the disk.
  3014. ;--------------------------------------------------------------------
  3015. osadd_ren_opsys    proc    near
  3016.         call    get_ostype        ;Query user for OP SYS
  3017.         or    bl,bl
  3018.         je    jmp_osadd_1
  3019.  
  3020.         push    di            ;Save ptr to op sys name
  3021.         mov    si,offset osadd_namestr
  3022.         xchg    di,si
  3023.         mov    cx,8            ;Only 8 characters in name
  3024.         rep     movsb
  3025.             mov     si,offset osadd_str4    ;Print old OS name
  3026.             call    write_linenorm          
  3027.  
  3028.             mov     si,offset osadd_str5    ;Prompt user for new OS name
  3029.             call    write_linenorm          
  3030.             mov     dx,0a29h
  3031.             mov     al,8            ;8 characters
  3032.             call    entry_box
  3033.             
  3034.         pop    di            ;Get pointer to table entry
  3035.             mov     si,bx            ;Copy ptr to new name
  3036.             rep     movsb            ;Copy name
  3037.         xor    ax,ax
  3038.         stosb                ;Terminate name
  3039.         mov    local_changed,1
  3040. jmp_osadd_1:
  3041.         xor    ax,ax
  3042.         ret
  3043. osadd_ren_opsys    endp
  3044.  
  3045. ;--------------------------------------------------------------------
  3046. ; OSADD EXIT - Sets the exit flag to return from this submenu
  3047. ;--------------------------------------------------------------------
  3048. osadd_exit    proc    near
  3049.         cmp    local_changed,0        
  3050.         clc
  3051.         je    osadd_exit_1
  3052.             mov     si,offset mboot_name    ;Open the MBOOT.SYS file to
  3053.             call    make_filename           ;  write opsys information.
  3054.  
  3055.         mov    si,dx            ;Copy ptr to ASCIIZ filename
  3056.         xor    cx,cx
  3057.         call    set_attributes        ;Clear file attributes
  3058.             mov     ax,3d02h
  3059.             int     21h
  3060.             jc      osadd_exit_error
  3061.  
  3062.         mov    bx,ax            ;Copy file handle
  3063.         mov    ax,4200h        ;Move file ptr to os table
  3064.         mov    dx,inst_boot_ptr
  3065.         xor    cx,cx
  3066.         int    21h        
  3067.             mov     ah,40h                  ;Write boot op sys data
  3068.             mov     dx,offset opsys_table
  3069.             mov     cx,inst_boot_size
  3070.             int     21h
  3071.             jc      osadd_exit_error
  3072.  
  3073.             mov     ah,3eh                  ;Close file
  3074.             int     21h
  3075.         mov    dx,si
  3076.         mov    cx,SYSFILE_ATTR
  3077.         call    set_attributes        
  3078.             jc      osadd_exit_error
  3079. osadd_exit_1:
  3080.         mov    al,-1            ;Set exit flag
  3081.             ret
  3082. osadd_exit_error:
  3083.         mov    si,offset osadd_err11
  3084.         stc
  3085.         jmp    short osadd_exit_1
  3086. osadd_exit    endp
  3087.  
  3088. main_osadd      endp
  3089.  
  3090. ;--------------------------------------------------------------------
  3091. ; MAIN DEFAULTS - Sets boot default values
  3092. ;--------------------------------------------------------------------
  3093. def_string1     db      20,08,"Current Defaults",0
  3094. def_string2     db      25,10,"Default Session:",0
  3095. def_string3     db      25,12,"Default Timeout:",0
  3096. def_string4     db      46,12,"Seconds",0
  3097. def_string6     db      15,14,"Enter Timeout Value in Seconds",0
  3098.  
  3099. default_msg1    db      "Defaults Not Changed",0
  3100. default_msg2    db      "No Default Session",0
  3101. default_msg3    db      "Indefinite  ",0
  3102. default_err1    db      "Invalid number",0
  3103.  
  3104. local_timeout   dw      0
  3105. local_default   db      0
  3106.  
  3107. def_chdef       db      "Change Default Session",0
  3108. def_chtime      db      "Change Timeout",0
  3109.  
  3110. default_table    dw    offset default_menu
  3111.         dw    offset default_ch_def
  3112.         dw    offset default_ch_time
  3113.         dw    offset default_exit
  3114.         dw    offset add_quit
  3115.  
  3116. default_menu    db      4,0                     ;Number of choices, Selected
  3117.             db      30,22                   ;Location of "Choices" prompt
  3118.             dw      0                       ;Timeout value
  3119.             db      0,0                     ;Col, Row of Timeout string
  3120.             db      25,17                   ;Column, Row of menu item
  3121.             dw      offset def_chdef        ;Offset of menu text
  3122.             db      25,18
  3123.             dw      offset def_chtime
  3124.             db      25,19
  3125.             dw      offset return_text
  3126.             db      25,20
  3127.             dw      offset quit_text
  3128.  
  3129. main_defaults   proc    near
  3130.             assume  cs:code,ds:code
  3131.             mov     al,boot_default         ;Copy system values to local
  3132.             mov     local_default,al        ;  variables.
  3133.             mov     ax,boot_timeout
  3134.             mov     local_timeout,ax
  3135. main_default_0:
  3136.             mov     si,offset def_string1
  3137.             call    write_linenorm
  3138.             mov     si,offset def_string2
  3139.             call    write_linenorm
  3140.             mov     si,offset def_string3
  3141.             call    write_linenorm
  3142.             mov     si,offset def_string4
  3143.             call    write_linenorm
  3144. main_default_1:
  3145.             mov     si,offset default_msg2  ;Point to no default msg
  3146.             xor     bx,bx
  3147.             or      bl,local_default        ;Get pointer to default entry
  3148.             je      main_default_3
  3149.             call    get_entry
  3150.             mov     si,bx
  3151. main_default_3:
  3152.             mov     dx,0a2ah                ;Row 10, Col 42
  3153.             call    write_line_at           ;Write string
  3154.  
  3155.             mov     ax,local_timeout        ;Get timeout value
  3156.         or    ax,ax
  3157.         jne    main_default_4
  3158.         mov    si,offset default_msg3    ;No timeout message
  3159.         mov    dx,0c2ah
  3160.         call    write_line_at
  3161.         jmp    short main_default_5
  3162. main_default_4:
  3163.             xor     dx,dx                   ;Convert to seconds
  3164.             mov     bx,18
  3165.             div     bx
  3166.             mov     dx,0c2ah                ;Write default timeout
  3167.             call    hex2asc
  3168. main_default_5:
  3169.             mov     si,offset default_table
  3170.             mov     al,1
  3171.             call    jump_menu
  3172.         cmp    al,-1
  3173.         jne    main_default_0
  3174.         mov    al,local_changed
  3175.         ret
  3176.  
  3177. ;--------------------------------------------------------------------
  3178. ; DEFAULT CH DEF - Changes the default session
  3179. ;--------------------------------------------------------------------
  3180. default_ch_def    proc    near
  3181.             mov     al,local_default        ;To select default session,
  3182.             call    get_session             ;  display menu of all
  3183.                                             ;  sessions.
  3184.             jc      default_ch_def_1    ;If carry set or no selection
  3185.         or    bl,bl            ;  skip default set.
  3186.             jc      default_ch_def_1
  3187.             mov     local_default,bl        ;Set new default
  3188.         mov    local_changed,1
  3189. default_ch_def_1:
  3190.         xor    al,al
  3191.             ret
  3192. default_ch_def    endp
  3193.  
  3194. ;--------------------------------------------------------------------
  3195. ; DEFAULT CH TIME - Changes the default timeout.
  3196. ;--------------------------------------------------------------------
  3197. default_ch_time    proc    near
  3198.             mov     si,offset def_string6
  3199.             call    write_linenorm
  3200.  
  3201.             mov     dx,0e2fh                ;Set cursor
  3202.             mov     al,3                    ;Allow 3 characters
  3203.             call    get_number
  3204.             jc      default_ch_time_1       ;Carry set, error
  3205.  
  3206.             mov     dx,18                   ;Convert seconds to ticks
  3207.             mul     dx
  3208.             mov     local_timeout,ax
  3209.         mov    local_changed,1
  3210.             call    scroll_half
  3211.             ret
  3212. default_ch_time_1:
  3213.             call    scroll_half
  3214.             mov     si,offset default_err1  ;Illegal number
  3215.             call    write_error
  3216.         ret
  3217. default_ch_time    endp
  3218.  
  3219. ;--------------------------------------------------------------------
  3220. ; DEFAULT_EXIT - Copys the new default values to the boot table.
  3221. ;--------------------------------------------------------------------
  3222. default_exit     proc    near
  3223.             mov     al,local_default        ;Copy local value to system
  3224.             mov     boot_default,al         ;  values.
  3225.             mov     ax,local_timeout
  3226.             mov     boot_timeout,ax
  3227.         mov    al,-1
  3228.             ret
  3229. default_exit    endp
  3230. main_defaults   endp
  3231.  
  3232. ;--------------------------------------------------------------------
  3233. ; INST INSTALL - Installs MultiBoot on a system.
  3234. ;--------------------------------------------------------------------
  3235. install_msg1    db    15,9,"WARNING!  You should back up your"
  3236.         db    " disk before",0
  3237. install_msg2    db    25,10,"installing MultiBoot.",0
  3238.  
  3239. install_msg    db    15,16,"Do You wish to install MultiBoot?",0
  3240. install1_msg    db    15,16,"Installing MultiBoot.  Please wait.",0
  3241. install_nomsg    db    "MultiBoot not installed",0
  3242.  
  3243. install_err1    db    "Operating system not found",0
  3244. install_err2    db    "Error writing operating system files",0
  3245. install_err3    db    "Error creating MBOOT.SYS",0
  3246. install_err4    db    "Error creating MultiBoot boot record",0
  3247.  
  3248. main_install    proc    near
  3249.             assume  cs:code,ds:code
  3250.             cmp     installed_flag,0    ;See if already installed
  3251.             je      install_0
  3252.             mov     si,offset errmsg21
  3253.             jmp     install_error1
  3254. install_0:
  3255.             mov     si,offset install_msg1
  3256.             call    write_linenorm
  3257.             mov     si,offset install_msg2
  3258.             call    write_linenorm
  3259.         mov    si,offset install_msg
  3260.         mov    al,1            ;Set default to Yes
  3261.         call    msg_box
  3262.         cmp    bl,1            ;See if answer Yes
  3263.         je    install_01
  3264.         mov    si,offset install_nomsg    ;Answer No, abort install.
  3265.         jmp    install_error1
  3266. install_01:
  3267.         mov    si,offset install1_msg    
  3268.         call    write_linenorm
  3269.  
  3270.         mov    al,drive_letter
  3271.         call    get_opsys        ;Get operating system
  3272.         mov    si,offset install_err1
  3273.             jc      jmp_install_error1
  3274.  
  3275.         mov    bx,101h            ;Write operating system with
  3276.         call    put_opsys        ;  bootfile = LASTBOOT.BIN
  3277.         mov    si,offset install_err2
  3278.         jc    jmp_install_error1
  3279.         
  3280.             mov     si,offset mboot_name    ;Write Boot extend file 
  3281.             call    make_filename           
  3282.             mov     si,offset boot_extend_start
  3283.             mov     cx,offset install_start - offset boot_extend_start
  3284.          mov    ax,SYSFILE_ATTR
  3285.         mov    no_DOS_flag,0    
  3286.         call    write_file
  3287.         mov    no_DOS_flag,1    
  3288.         mov    si,offset install_err3
  3289.         jc    jmp_install_error1
  3290. ; Modify Multiboot boot record with data from original boot record.
  3291.             push    ds                         ;Compute the amount of
  3292.             lds     si,databuff_ptr            ;  boot data on old boot
  3293.             mov     di,100h                    ;  record.  If too much,
  3294.             mov     cx,ds:[si+1]               ;  don't install.
  3295.             add     cx,3
  3296.             cmp     byte ptr ds:[si],0e9h      ;See if long jump
  3297.             je      install_2
  3298.             cmp     byte ptr ds:[si],0ebh      ;See if short jmp
  3299.             je      install_1
  3300.             pop     ds
  3301. jmp_install_error:
  3302.             jmp     install_error        ;If not a jump, error
  3303. jmp_install_error1:
  3304.             jmp     install_error1
  3305. install_1:
  3306.             xor     cx,cx
  3307.             mov     cl,ds:[si+1]            ;Get size of data area
  3308.             add     cx,2                    ;Add room for jmp
  3309. install_2:
  3310.             cmp     cx,offset bootcode - offset entry
  3311.             ja      install_error
  3312.             rep     movsb                   ;Copy boot data
  3313.             pop     ds
  3314.             mov     byte ptr cs:entry,0e9h   ;Copy jump opcode
  3315.             mov     dx,offset bootcode - 103h  ;Compute the jump value
  3316.             mov     word ptr cs:entry[1],dx
  3317.  
  3318.             mov     ax,dos_version
  3319.             cmp     ax,300h                 ;If DOS 2.x clear hidden sec
  3320.             ja      install_3               ;  count.
  3321.         mov    bp,100h
  3322.             mov     word ptr num_hidden_sec,0
  3323.             cmp     ax,314h                 ;If DOS 3.0 - 3.2, clear high
  3324.             ja      install_3               ;  word.
  3325.             mov     word ptr num_hidden_sec[2],0
  3326. install_3:
  3327. ; Write Multiboot boot record to target drive.
  3328.             mov     al,drive_letter
  3329.             mov     bx,offset entry         ;Get ptr to boot record
  3330.         call    put_bootrec
  3331.         mov    si,offset install_err4
  3332.             jc      install_error1
  3333.  
  3334.         mov    cx,4
  3335.         mov    si,offset opsys_table
  3336.         add    si,OPSYS_TYPE
  3337.         mov    bl,1
  3338. install_4:    
  3339.         cmp    word ptr [si],100h    ;See if OS/2 installed on
  3340.         je    install_5        ;  disk.
  3341.         inc    bl
  3342.         add    si,NEXT_OSENTRY
  3343.         loop    install_4
  3344.         jmp    short install_6
  3345. install_5:
  3346.         call    make_os_names
  3347.         call    make_filename
  3348.         mov    di,si
  3349.         mov    dx,offset os2boot_aname
  3350.         call    copy_file
  3351.         mov    dx,di            ;Hide boot file.
  3352.         mov    cx,SYSFILE_ATTR
  3353.         call    set_attributes        
  3354. install_6:
  3355.             mov     changed_flag,0
  3356.             mov     installed_flag,1        ;Set install flag
  3357.             xor     al,al                   ;Clear error flag
  3358. install_exit1:
  3359.             ret
  3360. install_error:
  3361.             mov     si,offset errmsg20
  3362. install_error1:
  3363.             stc
  3364.             jmp     short install_exit1
  3365. main_install    endp
  3366.  
  3367. ;--------------------------------------------------------------------
  3368. ; INST REMOVE - Removes Multiboot from a system.
  3369. ;--------------------------------------------------------------------
  3370. remove_msg    db    15,16,"Do you wish to remove MultiBoot?",0
  3371. remove1_msg    db    15,16,"Removing MultiBoot.  Please wait.",0
  3372. remove_nomsg    db    "MultiBoot not removed",0
  3373.  
  3374. main_remove     proc    near
  3375.             assume  cs:code,ds:code
  3376. ; Check to see if already installed
  3377.             cmp     installed_flag,0    ;If not installed, don't
  3378.             jne     remove_1        ;  remove.
  3379.             mov     si,offset errmsg23
  3380.             jmp     remove_error1
  3381. remove_1:
  3382.         mov    si,offset remove_msg    ;Verify remove request.
  3383.         mov    al,1            ;Set default to Yes
  3384.         call    msg_box
  3385.         cmp    bl,1            ;See if answer Yes
  3386.         mov    si,offset remove_nomsg
  3387.         jne    remove_error1
  3388.  
  3389.         mov    si,offset remove1_msg    ;Indicate removing.
  3390.         call    write_linenorm
  3391.  
  3392.         mov    si,offset lastboot_name    ;Read current op sys boot
  3393.         call    make_filename          ;  record from the file.
  3394.         push    es
  3395.         les    si,databuff_ptr
  3396.         call    read_file        ;Read LASTBOOT.BIN
  3397.         pop    es
  3398.             jc      remove_error
  3399. ;Write old boot record to boot sector
  3400.             mov     al,drive_letter
  3401.             push    ds
  3402.             lds     bx,databuff_ptr         ;Get ptr to data buffer
  3403.             call    put_bootrec             ;Write the boot record
  3404.             pop     ds
  3405.             jc      remove_error
  3406.  
  3407.         call    fixup_fat        ;Remove bad sectors in FAT
  3408.  
  3409.             mov     si,offset mboot_name    ;Delete MBOOT.SYS
  3410.         call    delete_file
  3411.         mov    si,offset lastboot_name    ;Delete LASTBOOT.BIN
  3412.         call    delete_file
  3413.  
  3414.         mov    cx,4
  3415.         mov    si,offset opsys_table    ;Scan operating system table
  3416.         xor    bx,bx            ;  deleteing the MBOOTOS files
  3417. remove_2:
  3418.         inc    bl
  3419.         cmp    byte ptr [si],80h    ;Is OS entry used?
  3420.         jae    remove_3
  3421.         call    delete_opsys
  3422. remove_3:
  3423.         add    si,NEXT_OSENTRY
  3424.         loop    remove_2
  3425.  
  3426.             mov     changed_flag,0
  3427.             mov     installed_flag,0        ;Clear install flag
  3428.         call    scroll_half        ;Clear screen
  3429.             clc                             ;Clear error flag
  3430.         mov    al,-1            ;Set terminate flag
  3431. remove_exit1:
  3432.             ret
  3433. remove_error:
  3434.             mov     si,offset errmsg22
  3435. remove_error1:
  3436.             stc
  3437.         mov    al,0
  3438.             jmp     short remove_exit1
  3439. main_remove     endp
  3440.  
  3441. ;--------------------------------------------------------------------
  3442. ; EXIT - Updates changes to installed files and exits program.
  3443. ;--------------------------------------------------------------------
  3444. exit_str0       db      15,14,"MultiBoot not installed.",0
  3445. exit_str1       db      15,16,"Do you wish to install MultiBoot?",0
  3446. exit_err1    db    "Installed data incompatible with this version.",0
  3447. exit            proc    near
  3448.             assume  cs:code,ds:code
  3449.         cmp    installed_flag,0    ;If not installed, ask if 
  3450.         jne    exit_1            ;  prog should install.
  3451.         mov    si,offset exit_str0
  3452.         call    write_linenorm
  3453.         mov    al,1            ;Default Yes
  3454.         mov    si,offset exit_str1        
  3455.         call    msg_box    
  3456.         cmp    bl,1
  3457.         jne    exit_3
  3458.         call    main_install        ;Install Multiboot
  3459.         jc    exit_4            
  3460.         jmp    short exit_3
  3461. exit_1:
  3462.             mov     si,offset mboot_name    ;Open the MBOOT.SYS file to
  3463.             call    make_filename           ;  write updated information.
  3464.  
  3465.         mov    si,dx            ;Copy ptr to ASCIIZ filename
  3466.         xor    cx,cx
  3467.         call    set_attributes        ;Clear file attributes
  3468.             mov     ax,3d02h
  3469.             int     21h
  3470.             jc      exit_3
  3471.  
  3472.         mov    bx,ax            ;Copy file handle
  3473.         mov    ax,4200h        ;Move file ptr to boot table
  3474.         mov    dx,inst_data_ptr
  3475.         xor    cx,cx
  3476.         int    21h        
  3477.             mov     ah,40h                  ;Write boot data
  3478.             mov     dx,offset boot_data1
  3479.             mov     cx,inst_data_size
  3480.             int     21h
  3481.  
  3482.         mov    ax,4200h        ;Move file ptr to boot table
  3483.         mov    dx,inst_sess_ptr
  3484.         xor    cx,cx
  3485.         int    21h        
  3486.             mov     ah,40h                  ;Write boot session data
  3487.             mov     dx,offset boot_array
  3488.             mov     cx,inst_sess_size
  3489.             int     21h
  3490.  
  3491.         mov    ax,4200h        ;Move file ptr to os table
  3492.         mov    dx,inst_boot_ptr
  3493.         xor    cx,cx
  3494.         int    21h        
  3495.             mov     ah,40h                  ;Write boot op sys data
  3496.             mov     dx,offset opsys_table
  3497.             mov     cx,inst_boot_size
  3498.             int     21h
  3499.  
  3500.             mov     ah,3eh                  ;Close file
  3501.             int     21h
  3502.         mov    dx,si
  3503.         mov    cx,SYSFILE_ATTR
  3504.         call    set_attributes        
  3505. exit_3:
  3506.             mov     al,-1            ;Set flag to end program
  3507. exit_4:
  3508.             ret
  3509. exit            endp
  3510.  
  3511. ;--------------------------------------------------------------------
  3512. ; QUIT - Quits program without changing installed files.
  3513. ;--------------------------------------------------------------------
  3514. quit_msg    db    20,15,"Do you wish to discard all changes made?",0
  3515. quit_msg1    db    20,9,"You have choosen to leave MultiBoot without",0
  3516. quit_msg2    db    17,10,"making your changes permanent.  To make your",0
  3517. quit_msg3    db    17,11,"changes permanent, answer No, then select",0
  3518. quit_msg4    db    17,12,"Update and Exit MultiBoot on the Main Menu.",0
  3519. quit            proc    near
  3520.             assume  cs:code,ds:code
  3521.         cmp    changed_flag,0
  3522.         je    quit_1
  3523.         mov    si,offset quit_msg1    ;Tell user what he/she is
  3524.         call    write_linenorm        ;  doing.
  3525.         mov    si,offset quit_msg2
  3526.         call    write_linenorm
  3527.         mov    si,offset quit_msg3
  3528.         call    write_linenorm
  3529.         mov    si,offset quit_msg4
  3530.         call    write_linenorm
  3531.         mov    si,offset quit_msg
  3532.         mov    al,2            ;Set default to No.
  3533.         call    msg_box
  3534.         mov    al,0
  3535.         cmp    bl,2            ;See if No.
  3536.         je    quit_2
  3537. quit_1:
  3538.         call    scroll_half
  3539.             mov     al,-1            ;Set terminate prog flag
  3540. quit_2:
  3541.             ret
  3542. quit            endp
  3543.  
  3544. ;--------------------------------------------------------------------
  3545. ; JUMP MENU - Displays a menu then calls the routines pointed to in
  3546. ;             in the jump table.
  3547. ; Entry: AL - Default selection
  3548. ;        SI - Offset of jump table 
  3549. ;--------------------------------------------------------------------
  3550. jump_menu       proc    near
  3551.             mov     bp,[si]                 ;Display main menu.
  3552.             mov     byte ptr [bp+MENU_SELECTED],al
  3553.         push    si
  3554.             call    menu
  3555.         pop    si
  3556.             jnc     jump_menu_2             ;Esc pressed -> Assume quit
  3557. jump_menu_1:
  3558.         mov    bl,[bp]            ;BL = last  choice
  3559. jump_menu_2:
  3560.             or      bl,bl                   ;If no cmd, assume quit.
  3561.             je      jump_menu_1        ;Convert menu choice to
  3562.             shl     bx,1                    ;  index into jump table of
  3563.             add     bx,si                   ;  routines.
  3564.             call    scroll_half        ;Clear lower half of screen.
  3565.         call    [bx]            ;Call routine.
  3566.             ret
  3567. jump_menu       endp
  3568.  
  3569. ;--------------------------------------------------------------------
  3570. ; GET SESS NAME - Querys the user for a session name
  3571. ; Entry: BL - Ptr to session entry
  3572. ; Exit:  CF - Set if Ctrl-C entered.
  3573. ;--------------------------------------------------------------------
  3574.  
  3575. get_sess_name   proc    near
  3576.         mov    ax,offset local_add1    ;Compute entry into 
  3577.         call    get_entry1        ;  local table.
  3578.         mov    bp,bx            ;Save ptr to table entry
  3579.             call    scroll_half             ;Clear screen
  3580.  
  3581.             mov     dx,0806h                ;Write header.
  3582.             mov     si,offset inst_text1
  3583.         call    write_line_at
  3584.  
  3585.             mov     di,bp                   ;Write session data to screen
  3586.             mov     dx,0a06h
  3587.             call    disp_session
  3588.  
  3589.         mov    si,offset add_str_msg1    ;Print message on how to
  3590.         call    write_linenorm        ;  return to add menu.
  3591.  
  3592.             mov     si,offset add_str4      ;Prompt user for Session name
  3593.             call    write_linenorm             
  3594.             mov     dx,0e34h                   
  3595.             mov     al,offset auto1 - offset name1 - 1
  3596.             call    entry_box
  3597.         jc    get_sess_exit
  3598.             mov     si,bx
  3599.             mov     di,bp                   ;Copy title to local buffer.
  3600.             rep     movsb
  3601.             mov     byte ptr [di],0         ;Terminate string
  3602.             mov     dh,14
  3603.             call    clear_line
  3604. get_sess_exit:
  3605.         ret
  3606. get_sess_name    endp
  3607.  
  3608. ;--------------------------------------------------------------------
  3609. ; ADD FILE - Asks user for a filename and verifys its correctness.
  3610. ; Entry: SI - Pointer to filename (CONFIG or AUTOEXEC)
  3611. ;--------------------------------------------------------------------
  3612. add_file_str    db      05,14,"Enter the file that will become the "
  3613. add_file_name   db      12 dup (" ")
  3614. add_file_str1   db      " file:",0
  3615.  
  3616. add_file_str2   db      05,14,"The file "
  3617. add_file_name0    db    12 dup (" ")
  3618.         db    "does not exist.",0
  3619. add_file_str3   db      05,16,"Do you want to copy the current "
  3620. add_file_name1  db      12 dup (" ")
  3621.             db      " file into this one?",0
  3622.  
  3623. add_file_err1   db      "A filename must be entered",0
  3624.  
  3625. add_file_err2   db      "The filename "
  3626. add_file_name2  db      12 dup (" ")
  3627.             db      " cannot be used",0
  3628.  
  3629. add_file_err3   db      "Error creating file",0
  3630. add_file_err4   db      "This file does not exist",0
  3631.  
  3632. add_file        proc    near
  3633.             push    si                      ;Save ptr to filename
  3634.  
  3635.             mov     dh,10
  3636.             call    clear_line
  3637.             mov     di,local_selection      ;Write session data to screen
  3638.             call    disp_session
  3639.  
  3640.             mov     al," "                  ;Clear file names from strings
  3641.             mov     di,offset add_file_name
  3642.             mov     cx,12
  3643.             rep     stosb
  3644.             mov     di,offset add_file_name0
  3645.             mov     cx,12
  3646.             rep     stosb
  3647.             mov     di,offset add_file_name1
  3648.             mov     cx,12
  3649.             rep     stosb
  3650.             mov     di,offset add_file_name2
  3651.             mov     cx,12
  3652.             rep     stosb
  3653.  
  3654.             pop     bp            ;Get ptr to filename
  3655.         mov    si,bp            
  3656.             mov     di,offset add_file_name
  3657.             call    fn2asciiz
  3658.             mov     bx,cx
  3659.             mov     byte ptr [bx+si]," "    ;Erase zero
  3660.  
  3661.             push    si                       ;Copy filename to other
  3662.             mov     di,offset add_file_name1 ;  messages
  3663.             push    cx
  3664.             rep     movsb
  3665.             pop     cx
  3666.             pop     si
  3667.             mov     di,offset add_file_name2
  3668.             rep     movsb
  3669. add_file_1:
  3670.             mov     dh,14                   ;Clear line for query.
  3671.             call    clear_line
  3672.  
  3673.             mov     si,offset add_file_str  ;Assemble prompt message using
  3674.             call    write_linenorm          ;  destination filename
  3675.             mov     si,offset add_file_str1 ;  provided.
  3676.             call    write_linenorm
  3677.  
  3678.         mov    si,offset add_str_msg1    ;Print message on how to
  3679.         call    write_linenorm        ;  return to add menu.
  3680.  
  3681.             mov     dx,0e3ch                ;Get filename max char = 12
  3682.             mov     al,12
  3683.             call    entry_box
  3684.         pushf
  3685.             mov     dh,22            ;Erase ctl-break message
  3686.             call    clear_line
  3687.         popf
  3688.         jnc    add_file_11
  3689.         jmp    add_file_4
  3690. add_file_11:
  3691.             or      cx,cx                   ;If zero length string, error
  3692.             mov     si,offset add_file_err1
  3693.             je      add_file_error
  3694.             mov     si,cx
  3695.             mov     byte ptr [bx+si],0      ;Terminate name with zero
  3696.  
  3697.             push    cx
  3698.             mov     si,bx
  3699.             mov     di,offset temp_buff
  3700.             call    asciiz2fn
  3701.             mov     di,bp                   ;Make sure destination name
  3702.             mov     cx,11                   ;  not used.
  3703.             repe    cmpsb
  3704.             pop     cx
  3705.             jne     add_file_2
  3706.             mov     si,offset add_file_err2 ;Can't use dest filename
  3707. add_file_error:
  3708.             call    write_error
  3709.             jmp     short add_file_1
  3710. add_file_2:
  3711.             mov     si,offset temp_buff     ;Create filename from 8.3 
  3712.             call    make_filename           ;  format.
  3713.  
  3714.             mov     ax,3d00h                ;Open file, read only
  3715.             int     21h
  3716.             jnc     add_file_3
  3717.  
  3718.         mov    si,offset temp_buff    ;Add filename to error msg
  3719.             mov     di,offset add_file_name0
  3720.             call    fn2asciiz
  3721.             mov     bx,cx
  3722.             mov     byte ptr [bx+si]," "    ;Erase terminating zero
  3723.  
  3724.             mov     si,offset add_file_err4 ;Indicate to the user that
  3725.             call    write_error             ;  the file can't be found.
  3726.  
  3727.             mov     si,bp                   ;Get destination file
  3728.         call    find_file
  3729.             jc      add_file_1              ;If no file, skip copy question
  3730.  
  3731.             mov     dh,14                   ;File does not exist, prompt
  3732.             call    clear_line              ;  user for choices.
  3733.  
  3734.             mov     si,offset add_file_str2
  3735.             call    write_linenorm
  3736.             mov     al,1                    ;Set default answer
  3737.             mov     si,offset add_file_str3 ;See if user wants to copy
  3738.             call    msg_box                 ;  the current autoexec or
  3739.             mov     dh,14                   ;  config file to this one.
  3740.             call    clear_line
  3741.             cmp     bl,1                    ;If not Yes, skip copy.
  3742.             je      add_file_21
  3743.             jmp     add_file_1
  3744. add_file_21:
  3745.         mov    si,bp            
  3746.             mov     di,offset temp_buff+40
  3747.             call    make_filename
  3748.             mov     di,offset filename_buff    ;Copy autoexec or config to
  3749.             call    copy_file        ;  new filename
  3750.             mov     si,offset add_file_err3
  3751.             jc      add_file_error
  3752. add_file_3:
  3753.             mov     si,offset temp_buff     ;Point SI to new filename
  3754.             clc
  3755. add_file_4:
  3756.             ret
  3757. add_file        endp
  3758.  
  3759. ;--------------------------------------------------------------------
  3760. ; GET SESSION - Displays a session menu.
  3761. ; Entry: AL - Default session.
  3762. ; Exit:  BX - Session number selected.
  3763. ;--------------------------------------------------------------------
  3764. get_sess_str    db      20,7,"Select Session",0
  3765. get_session     proc    near
  3766.         mov    bx,1            ;If only one session, don't
  3767.         cmp    session_count,1        ;  ask user to pick.
  3768.         ja     get_session_1
  3769.         jmp    short get_session_3
  3770. get_session_1:
  3771.             mov     bp,offset boot_menu
  3772. get_session_2:
  3773.             push    ax
  3774.             call    scroll_half              ;Clear screen.
  3775.             mov     si,offset get_sess_str   ;Display message
  3776.             call    write_linenorm
  3777.             pop     ax
  3778.             mov     [bp+MENU_SELECTED],al   ;Set default
  3779.             mov     word ptr [bp+MENU_TIMEOUT],0
  3780.             call    menu
  3781. get_session_3:
  3782.             pushf                           ;Carry indicates <esc> pressed
  3783.             call    scroll_half
  3784.             popf
  3785.             ret
  3786. get_session     endp
  3787.  
  3788. ;--------------------------------------------------------------------
  3789. ; GET OSTYPE - Prompts the user to select an operating system.
  3790. ; Exit:   BL - OS selection
  3791. ;--------------------------------------------------------------------
  3792. os_menu_str1    db      05,14,"Select Operating System",0
  3793.  
  3794. os_menu         db      4,1                     ;Number of choices, Selected
  3795.             db      30,22                   ;Location of "Choices" prompt
  3796.             dw      0                       ;Timeout value
  3797.             db      0,0                     ;Col, Row of Timeout string
  3798.             db      25,17                   ;Column, Row of menu item
  3799.             dw      offset os_name1         ;Offset of menu text
  3800.             db      25,18
  3801.             dw      offset os_name2
  3802.             db      25,19
  3803.             dw      offset os_name3
  3804.             db      25,20
  3805.             dw      offset os_name4
  3806.  
  3807. get_ostype    proc    near
  3808.             mov     si,offset os_menu_str1  ;Prompt user for the
  3809.             call    write_linenorm          ;  operating system 
  3810.             mov     bp,offset os_menu       ;Operating system menu
  3811.             call    menu
  3812.         pushf
  3813.             mov     cx,0e00h                ;Clear screen
  3814.             mov     dx,1950h
  3815.             call    scroll_block
  3816.         xor    di,di
  3817.         popf                ;If <esc> no choice made
  3818.         jc    get_ostype_exit
  3819.         call    get_os_entry
  3820.         clc
  3821. get_ostype_exit:
  3822.         ret
  3823. get_ostype    endp
  3824.  
  3825. ;--------------------------------------------------------------------
  3826. ; MAKE FILENAME - Adds drive and directory stuff to 8.3 filename.
  3827. ; Entry: SI - Pointer to filename
  3828. ; Exit:  SI = DX - Pointer to filename
  3829. ;--------------------------------------------------------------------
  3830. make_filename   proc    near
  3831.         push    cx
  3832.         push    di
  3833.             mov     di,offset filename_buff
  3834.         push    di
  3835.             mov     al,drive_letter         ;Copy drive letter
  3836.             stosb
  3837.             mov     ax,"\:"                 ;Add DOS dir stuff
  3838.             stosw
  3839.             call    fn2asciiz               ;Append filename
  3840.             pop     si
  3841.             mov     dx,si                   ;Copy pointer to filename
  3842.         pop    di
  3843.         pop    cx
  3844.             ret
  3845. make_filename   endp
  3846.  
  3847. ;--------------------------------------------------------------------
  3848. ; READ FILE - Opens a file, reads the data, and closes the file.
  3849. ; Entry: DS:DX - Pointer to source ASCIIZ filename
  3850. ;        ES:SI - Pointer to data buffer
  3851. ; Exit:     CX - Bytes read
  3852. ;--------------------------------------------------------------------
  3853. read_file    proc    near
  3854.         call    set_crit_vec        ;Set crit vec to int routine
  3855.             mov     ax,3d00h                ;Open file, read only
  3856.             int     21h
  3857.         jc    read_file_exit
  3858.             mov     bx,ax                   ;Copy file handle
  3859.  
  3860.             push    ds                      ;Read file into data buffer
  3861.         push    es
  3862.         pop    ds
  3863.             mov     dx,si        
  3864.             mov     cx,65013                ;Buffer size
  3865.             mov     ah,3fh                  ;Read file
  3866.             int     21h
  3867.             mov     cx,ax                   ;Save bytes read
  3868.              pop     ds
  3869.         jc    read_file_exit
  3870.  
  3871.             mov     ah,3eh                  ;Close file
  3872.             int     21h
  3873. read_file_exit:
  3874.             call    reset_crit_vec        ;Restore critical error vec
  3875.         ret
  3876. read_file    endp
  3877.  
  3878. ;--------------------------------------------------------------------
  3879. ; WRITE FILE - Creates a file and writes data to the file
  3880. ; Entry:    AX - Attributes for destination file
  3881. ;           CX - Size of data
  3882. ;        DS:DX - Pointer to desination  ASCIIZ filename
  3883. ;        ES:SI - Pointer to data 
  3884. ;--------------------------------------------------------------------
  3885. write_file      proc    near
  3886.         push    cx            ;Save size of data
  3887.         call    set_crit_vec        ;Set crit vec to int routine
  3888.             mov     cx,ax                   ;Copy attributes
  3889.             mov     ah,3ch                  ;Create file.
  3890.             int     21h
  3891.             mov     bx,ax                   ;Copy file handle
  3892.         pop    cx            ;Restore data size
  3893.             jc      write_file_exit
  3894.  
  3895.         push    ds
  3896.         push    es
  3897.         pop    ds
  3898.         mov    dx,si            ;Copy pointer to data
  3899.             mov     ah,40h                  ;Write file
  3900.             int     21h
  3901.         pop    ds
  3902.         jc    write_file_exit
  3903.             mov     ah,3eh                  ;Close file
  3904.             int     21h
  3905. write_file_exit:
  3906.             call    reset_crit_vec        ;Restore critical error vec
  3907.             ret
  3908. write_file      endp
  3909.  
  3910. ;--------------------------------------------------------------------
  3911. ; READ ABSOLUTE - Reads sectors from the disk.
  3912. ; Entry:   AL - Letter of drive to read
  3913. ;          CX - Number of sectors to read.  
  3914. ;       SI,DX - Sector to start read (SI only used on huge disks)
  3915. ;       DS:BX - Pointer to data buffer. 
  3916. ;--------------------------------------------------------------------
  3917. read_abs_hstruc    =    $            ;Needed for >32M disks
  3918. read_abs_start    dd    0            ;Starting sector
  3919. read_abs_cnt    dw    0            ;Number of sectors to read
  3920. read_abs_dbp    dd    0            ;Data buffer ptr
  3921.  
  3922. read_absolute   proc    near
  3923.         push    bx
  3924.         push    cx
  3925.         push    ds
  3926.         call    set_crit_vec        ;Set crit vec to int routine
  3927.         call    huge_disk_check
  3928.         jc    read_abs_2
  3929.         je    read_abs_1
  3930.         push    ds            ;Save ptr to data buffer
  3931.         push    bx
  3932.         push    cs
  3933.         pop    ds
  3934.         mov    bx,offset read_abs_hstruc
  3935.         mov    [bx],dx            ;More than 64K sectors
  3936.         mov    [bx+2],si        ;  -> huge disk uses a
  3937.         mov    [bx+4],cx        ;  different format
  3938.         pop    [bx+6]            ;  than std int 25h.    
  3939.         pop    [bx+8]
  3940.         mov    cx,-1
  3941. read_abs_1:
  3942.             sub     al,'A'            ;Convert to hex (0 base)
  3943.             int     25h                     ;DOS Absolute Disk Read
  3944.             pop     bx                      ;Clean off old flags
  3945.             cld
  3946. read_abs_2:
  3947.             call    reset_crit_vec        ;Restore critical error vec
  3948.         pop    ds
  3949.         pop    cx
  3950.         pop    bx
  3951.             ret
  3952. read_absolute   endp
  3953.  
  3954. ;--------------------------------------------------------------------
  3955. ; WRITE ABSOLUTE - Writes sectors to the disk.
  3956. ; Entry:   AL - Letter of drive to write
  3957. ;          CX - Number of sectors to write  
  3958. ;       SI,DX - Sector to start write (SI only used on huge disks)
  3959. ;       DS:BX - Pointer to data buffer. 
  3960. ;--------------------------------------------------------------------
  3961. write_absolute  proc    near
  3962.         push    bx
  3963.         push    cx
  3964.         push    ds
  3965.         call    set_crit_vec        ;Set crit vec to int routine
  3966.         call    huge_disk_check
  3967.         jc    write_abs_2    
  3968.         je    write_abs_1
  3969.         push    ds            ;Save data buffer pointer
  3970.         push    bx
  3971.         push    cs
  3972.         pop    ds
  3973.         mov    bx,offset read_abs_hstruc
  3974.         mov    [bx],dx            ;More than 64K sectors
  3975.         mov    [bx+2],si        ;  -> huge disk uses a
  3976.         mov    [bx+4],cx        ;  different format
  3977.         pop    [bx+6]            ;  than std int 26h.    
  3978.         pop    [bx+8]
  3979.         mov    cx,-1                
  3980. write_abs_1:
  3981.             sub     al,'A'            ;Convert to hex (0 based)
  3982.             int     26h                     ;DOS Absolute Disk Write
  3983.             pop     bx                      ;Clean off old flags
  3984.             cld
  3985. write_abs_2:
  3986.             call    reset_crit_vec        ;Restore critical error vec
  3987.         pop    ds
  3988.         pop    cx
  3989.         pop    bx
  3990.             ret
  3991. write_absolute  endp
  3992.  
  3993. ;--------------------------------------------------------------------
  3994. ; HUGE DISK CHECK - Checks if disk is greater than 32 Meg
  3995. ; Entry: AL - Disk to check
  3996. ; Exit:  ZF - Clear if > 32 Meg disk
  3997. ;        CF - Set if error
  3998. ;        DI - Sectors per cluster
  3999. ;--------------------------------------------------------------------
  4000. last_disk_read    db    -1
  4001. last_disk_huge    db    0
  4002. last_disk_spc     dw    0
  4003. huge_disk_check    proc    near
  4004.         push    ax
  4005.         push    bx
  4006.         push    cx
  4007.         push    dx
  4008.         cmp    al,last_disk_read    ;Save last disk checked, if
  4009.         jne    huge_disk_check_1    ;  same as last disk, just
  4010.         mov    di,last_disk_spc    ;  get saved answer.
  4011.         cmp    last_disk_huge,0    
  4012.         jmp    short huge_disk_check_3
  4013. huge_disk_check_1:
  4014.         mov    last_disk_read,al
  4015.         mov    last_disk_huge,0
  4016.         mov    dl,al            ;Copy disk number
  4017.         sub    dl,40h            ;Convert ASCII to hex (1 base)
  4018.         mov    ah,36h            ;DOS Get Free disk space
  4019.         int    21h        
  4020.         cmp    ax,-1
  4021.         jne    huge_disk_check_2
  4022.         mov    last_disk_read,-1
  4023.         jmp    short huge_disk_check_4
  4024. huge_disk_check_2:
  4025.         mov    di,ax            ;Save sectors per cluster
  4026.         mov    last_disk_spc,di
  4027.         mul    dx
  4028.         or    dx,dx            ;See if more than 64K sectors
  4029.         je    huge_disk_check_3
  4030.         mov    last_disk_huge,1
  4031. huge_disk_check_3:
  4032.         clc
  4033. huge_disk_check_4:
  4034.         pop    dx
  4035.         pop    cx
  4036.         pop    bx
  4037.         pop    ax
  4038.         ret
  4039. huge_disk_check    endp
  4040.  
  4041. ;--------------------------------------------------------------------
  4042. ; COPY FILE - Copies a file
  4043. ; Entry: DX - Pointer to source ASCIIZ filename
  4044. ;        DI - Pointer to destination ASCIIZ filename
  4045. ;--------------------------------------------------------------------
  4046. copy_file       proc    near
  4047.         push    es
  4048.         les    si,databuff_ptr
  4049.         call    read_file    
  4050.         jc    copy_file_exit
  4051.             mov     dx,di                   ;Point to new file name
  4052.             xor     ax,ax                   ;Normal attributes
  4053.         call    write_file        
  4054. copy_file_exit:
  4055.         pop    es
  4056.             ret
  4057. copy_file       endp
  4058.  
  4059. ;--------------------------------------------------------------------
  4060. ; DELETE FILE - Deletes file
  4061. ; Entry: SI - Pointer to filename in 8.3 format
  4062. ;--------------------------------------------------------------------
  4063. delete_file     proc    near
  4064.         push    cx
  4065.             push    si
  4066.             call    make_filename           ;Convert to ASCIIZ
  4067.         xor    cx,cx
  4068.         call    set_attributes
  4069.  
  4070.             mov     ah,41h                  ;DOS Delete File
  4071.             int     21h
  4072.         pop    si
  4073.         pop    cx    
  4074.             ret
  4075. delete_file     endp
  4076.  
  4077. ;--------------------------------------------------------------------
  4078. ; SET ATTRIBUTES - Sets file attribute flags.
  4079. ; Entry: CX - file attributes
  4080. ;        DX - pointer to ASCIIZ filename. 
  4081. ;--------------------------------------------------------------------
  4082. set_attributes  proc    near
  4083.             mov     ax,4301h                ;DOS Set Attributes
  4084.             int     21h
  4085.             ret
  4086. set_attributes  endp
  4087.  
  4088. ;--------------------------------------------------------------------
  4089. ; MAKE BOOTFILE - Writes the boot record data in the data buffer 
  4090. ;                 to a file on the disk.
  4091. ; Entry: SI - Destination filename in 8.3 format
  4092. ;--------------------------------------------------------------------
  4093. make_bootfile    proc    near
  4094.         push    es
  4095.         les    si,databuff_ptr        ;Get ptr to boot record
  4096.         mov    ax,SYSFILE_ATTR        ;Get attributes
  4097.         mov    cx,512            ;Boot file size
  4098.         call    write_file
  4099.         pop    es
  4100.         ret
  4101. make_bootfile    endp
  4102.  
  4103. ;--------------------------------------------------------------------
  4104. ; GET BOOTREC - Reads the boot record into the data buffer.
  4105. ; Entry: AL - Letter of drive to read
  4106. ;--------------------------------------------------------------------
  4107. get_bootrec     proc    near
  4108.             mov     cx,1                    ;Read 1 sector
  4109.             xor     dx,dx                   ;Read 1st sector
  4110.         xor    si,si
  4111.             push    ds
  4112.             lds     bx,databuff_ptr         ;Get ptr to data buffer
  4113.             call    read_absolute           ;DOS Absolute Disk Read
  4114.             pop     ds
  4115.             ret
  4116. get_bootrec     endp
  4117.  
  4118. ;--------------------------------------------------------------------
  4119. ; PUT BOOTREC - Writes the boot record with data from the data buffer.
  4120. ; Entry:    AL - Drive letter to write
  4121. ;        DS:BX - Segment:Offset of boot record to write.
  4122. ;--------------------------------------------------------------------
  4123. put_bootrec     proc    near
  4124.             mov     cx,1                    ;Write 1 sector
  4125.             xor     dx,dx                   ;Write 1st sector
  4126.         xor    si,si
  4127.             call    write_absolute          ;DOS Absolute Disk Write
  4128.             ret
  4129. put_bootrec     endp
  4130.  
  4131. ;--------------------------------------------------------------------
  4132. ; COPY BPB - Copies a BIOS parameter block.
  4133. ; Entry: AL - 0 = to MBOOT boot rec, 1 = from MBOOT bootrec
  4134. ;--------------------------------------------------------------------
  4135. copy_bpb    proc    near
  4136.         push    cx
  4137.         push    ds
  4138.         push    es
  4139.         les    di,databuff_ptr        ;Offset of boot rec BPB
  4140.         add    di,11
  4141.         mov    si,10bh            ;Offset of MBOOT BPB
  4142.         or    al,al
  4143.         jne    copy_bpb_1
  4144.         xchg    si,di            ;Exchange pointers.
  4145.         push    es
  4146.         push    ds
  4147.         pop    es
  4148.         pop    ds
  4149. copy_bpb_1:
  4150.         mov    cx,32            ;Copy BPB    
  4151.         rep    movsb
  4152.         or    al,al
  4153.         je    copy_bpb_2
  4154.         cmp    cs:[drive_letter],"C"
  4155.         jb    copy_bpb_2
  4156.         cmp    byte ptr es:[1fdh],0
  4157.         jne    copy_bpb_2
  4158.         mov    byte ptr es:[1fdh],80h
  4159. copy_bpb_2:
  4160.         pop    es
  4161.         pop    ds
  4162.         pop    cx
  4163.         ret
  4164. copy_bpb    endp
  4165.  
  4166. ;--------------------------------------------------------------------
  4167. ; COPY OS NAME - Reads the operating system name from the OEM field
  4168. ;                of the boot record.
  4169. ; Entry: AL - Operating system type.
  4170. ;        BL - Operating system number.
  4171. ;--------------------------------------------------------------------
  4172. copy_os_name    proc    near
  4173.         call    get_os_entry        ;Get index into the os table 
  4174.         mov    word ptr [di+OPSYS_TYPE],cx
  4175.             push    di
  4176.         push    si
  4177.         push    ds
  4178.             lds     si,databuff_ptr         ;Copy the OEM name to the 
  4179.             add     si,3                    ;  field pointed to by
  4180.             mov     cx,8                    ;  DI.
  4181.             rep     movsb
  4182.         pop    ds
  4183.         pop    si
  4184.             pop     di
  4185.         add    di,9
  4186.         mov    si,offset ibmbio_name    ;Copy the proper names of the
  4187.         cmp    al,1            ;  os files to the os table.
  4188.         jb    copy_os_name_1
  4189.         ja    copy_os_name_2
  4190.         mov    si,offset iosys_name
  4191. copy_os_name_1:
  4192.         mov    cx,22            ;Copy both names at the same
  4193.         rep    movsb            ;  time.
  4194. copy_os_name_2:
  4195.         ret
  4196. copy_os_name    endp
  4197.  
  4198. ;--------------------------------------------------------------------
  4199. ; GET OPSYS - Gets the operating system files from a disk
  4200. ; Entry: AL - Drive letter to read operating system
  4201. ; Exit:  CF - Set if error
  4202. ;        AL - Return code:  
  4203. ;             0 - PC DOS     3 - MultiBoot   6 - Read error
  4204. ;             1 - MS DOS     4 - Unbootable  7 - OS too large
  4205. ;             2 - OS/2 disk  5 - Unknown
  4206. ;        AH - 1 if OS/2 system on disk
  4207. ;        CX - Number of consecutive clusters used by DOS
  4208. ;        DX - Number of consecutive clusters used by IO.SYS
  4209. ;     CF - Set if error
  4210. ;        opsys_ostype, iosys_size, doscom_size updated.
  4211. ;--------------------------------------------------------------------
  4212. get_opsys     proc    near
  4213.         mov    bl,drive_letter
  4214.         push    bx
  4215.         mov    drive_letter,al
  4216.         call    check_os        ;See what type of OS loaded
  4217.         mov    opsys_ostype,bx        ;  on disk.
  4218.         mov    bp,offset ibmbio_name    
  4219.         cmp    al,1            ;If PC DOS use different
  4220.         ja    get_opsys_error1    ;  names from MS DOS
  4221.         jb    get_opsys_1
  4222.         mov    bp,offset iosys_name
  4223. get_opsys_1:
  4224.         push    ax
  4225.         push    cx
  4226.         push    dx
  4227.         mov    iosys_size,0
  4228.         mov    si,bp            ;Copy ptr to first name
  4229.         call    make_filename
  4230.         push    es
  4231.         les    si,databuff_ptr
  4232.         add    si,512            ;Skip past boot data
  4233.         call    read_file
  4234.         pop    es
  4235.         mov    al,6
  4236.         jc    get_opsys_error
  4237.         mov    al,7            ;Error, os file too big
  4238.         cmp    cx,65013
  4239.         jae    get_opsys_error
  4240.         mov    iosys_size,cx
  4241.  
  4242.         mov    doscom_size,0
  4243.         mov    si,bp            ;Copy ptr to first name
  4244.         add    si,11            ;Point to second name
  4245.         call    make_filename
  4246.         push    es
  4247.         les    si,databuff1_ptr
  4248.         call    read_file
  4249.         pop    es
  4250.         mov    al,6
  4251.         jc    get_opsys_error
  4252.         mov    al,7            ;Error, os file too big
  4253.         cmp    cx,65013
  4254.         jae    get_opsys_error
  4255.         mov    doscom_size,cx        ;Save DOSCOM file size
  4256.         pop    dx
  4257.         pop    cx
  4258.         pop    ax
  4259.         clc
  4260. get_opsys_exit1:
  4261.         mov    bp,ax
  4262.         pop    ax
  4263.         mov    drive_letter,al        ;Restore target disk letter
  4264.         mov    ax,bp
  4265.         ret
  4266. get_opsys_error:
  4267.         add    sp,6            ;Clean off stack
  4268. get_opsys_error1:
  4269.         stc
  4270.         jmp    short get_opsys_exit1
  4271. get_opsys     endp
  4272.  
  4273. ;--------------------------------------------------------------------
  4274. ; CHECK SIZE - Compares the size of two numbers to the nearest sector
  4275. ; Entry: BX - File 1 size in bytes
  4276. ;        CX - File 2 size in bytes
  4277. ; Exit:  Flags set from compare
  4278. ;--------------------------------------------------------------------
  4279. check_size    proc    near        
  4280.         push    ax
  4281.         mov     ax,bx
  4282.         xor    dx,dx            ;Clear high word
  4283.         mov    bx,512            ;Div by sector size
  4284.         div    bx
  4285.         xchg    ax,cx            ;Get second number
  4286.         xor    dx,dx
  4287.         div    bx            ;Div second number
  4288.         cmp    ax,cx            ;Compare results
  4289.         pop    ax
  4290.         ret
  4291. check_size    endp
  4292. ;--------------------------------------------------------------------
  4293. ; PUT OPSYS - Saves the operating system to files on the disk
  4294. ; Entry: BL - Operating system number
  4295. ;        BH - 1 = Make bootfile name LASTBOOT.BIN
  4296. ;--------------------------------------------------------------------
  4297. put_opsys    proc    near        
  4298.         push    bp
  4299.         call    make_os_names        ;Generate names for files
  4300.         push    si
  4301.         or     bh,bh
  4302.         je    put_opsys_1
  4303.         mov    si,offset lastboot_name
  4304. put_opsys_1:
  4305.         call    make_filename
  4306.         xor    cx,cx
  4307.         call    set_attributes
  4308.         call    make_bootfile        ;Write boot rec to file.
  4309.         pop    si
  4310.  
  4311.         add    si,11            ;Point to iosys name
  4312.         mov    bp,si
  4313.         call    make_filename
  4314.         xor    cx,cx
  4315.         call    set_attributes
  4316.         push    es
  4317.         les    si,databuff_ptr        ;Load ptr to SYS file data
  4318.         add    si,512
  4319.         mov    cx,iosys_size        ;Set size
  4320.         mov    ax,SYSFILE_ATTR        ;Set attributes
  4321.         call    write_file        ;Write IO.SYS file
  4322.         pop    es
  4323.         jc    put_os_exit
  4324.  
  4325.         mov    si,bp
  4326.         add    si,11            ;Point to doscom name
  4327.         call    make_filename
  4328.         xor    cx,cx
  4329.         call    set_attributes    
  4330.         push    es
  4331.         les    si,databuff1_ptr        
  4332.         mov    cx,doscom_size        ;Set size
  4333.         mov    ax,SYSFILE_ATTR        ;Set attributes
  4334.         call    write_file        ;Write MSDOS.COM file
  4335.         pop    es
  4336. put_os_exit:    clc
  4337.         pop    bp
  4338.         ret
  4339. put_opsys    endp
  4340.  
  4341. ;--------------------------------------------------------------------
  4342. ; DELETE OPSYS - Deletes the MBOOT operating system files from the disk.
  4343. ; Entry: BL - Operating system number
  4344. ;--------------------------------------------------------------------
  4345. delete_opsys    proc    near
  4346.         push    si
  4347.         push    bx
  4348.         call    make_os_names        ;Get names of op sys files
  4349.         call    delete_file        ;Delete boot rec file
  4350.         add    si,11
  4351.         call    delete_file        ;Delete IO.SYS file
  4352.         add    si,11
  4353.         call    delete_file        ;Delete MSDOS.COM file
  4354.         pop    bx
  4355.         call    get_os_entry
  4356.         mov    byte ptr [di],80h    ;Delete entry in opsys table
  4357.         pop    si
  4358.         ret
  4359. delete_opsys    endp
  4360. ;--------------------------------------------------------------------
  4361. ; CHECK OS - Reads the boot record to determine the type of operating
  4362. ;            system currently loaded.
  4363. ; Exit:  AL - Type of operating system loaded:
  4364. ;             0 - PC DOS     2 - OS/2        4 - Not a bootable disk
  4365. ;             1 - MS DOS     3 - MultiBoot   5 - Unknown OS type
  4366. ;        AH - 1 if OS/2 system files are loaded (if AL = 0, 1, or 2)
  4367. ;        BX - DOS System file configuration:
  4368. ;             20 = Consec files, sectors
  4369. ;             30 = IO.SYS Consec. MSDOS.SYS not consec
  4370. ;             40 = IO.SYS not Consec
  4371. ;        CX - Number of consecutive clusters used by DOS
  4372. ;        DX - Number of consecutive clusters used by IO.SYS
  4373. ;--------------------------------------------------------------------
  4374. check_os    proc    near
  4375.         mov    al,drive_letter
  4376.             call    get_bootrec             ;Load boot record.
  4377.         mov    ax,00ffh
  4378.         jc    check_os_exit        ;If error loading, exit
  4379.  
  4380.             mov     di,offset mboot_name    ;Check if Multiboot is
  4381.             call    find_filename        ;  installed on drive.
  4382.         mov    ax,3            ;Multiboot installed
  4383.             jnc     check_os_exit
  4384.  
  4385.         xor    bp,bp
  4386.         mov    di,offset os2ldr_name    ;See if OS/2 disk
  4387.         call    find_filename
  4388.         mov    ax,2            ;OS/2 disk
  4389.         jnc    check_os_exit
  4390.  
  4391.         mov    di,offset ibmbio_name    ;See if PC DOS disk
  4392.         call    find_filename
  4393.         jnc    check_os_1
  4394.  
  4395.         inc    bp
  4396.         mov    di,offset iosys_name    ;See if MS DOS disk
  4397.         call    find_filename
  4398.         mov    ax,5            ;Error, unknown DOS type
  4399.         jc    check_os_exit
  4400. check_os_1:
  4401.         mov    ax,bp
  4402.         call    get_sys_size        ;Get size of DOS file area
  4403.         mov    bx,ax            ;  on disk.
  4404.         mov    ax,4
  4405.         jc    check_os_exit        ;CF=1 not bootable.
  4406. check_os_2:
  4407.         push    bx            ;Save DOS config
  4408.         push    cx            ;Save DOS size
  4409.         push    dx            ;Save IO.SYS size
  4410.         mov    si,offset os2ldr_name    ;See if OS/2 system files
  4411.         call    find_first           ;  on disk.  Start with OS2LDR
  4412.         jc    check_os_3
  4413.         mov    si,offset os2knl_name    ;Look for OS2KRNL
  4414.         call    find_first        
  4415.         jc    check_os_3
  4416.         mov    si,offset os2boot_aname    ;Look for \OS2\SYSTEM\BOOT.OS2
  4417.         mov    al,drive_letter
  4418.         mov    [si],al
  4419.         call    find_first1        
  4420.         jc    check_os_3
  4421.         or    bp,0100h        ;Set OS/2 found flag
  4422. check_os_3:
  4423.         mov    ax,bp            ;Get OS type
  4424.         pop    dx            ;Get IO.SYS size
  4425.         pop    cx            ;Get DOS size
  4426.         pop    bx            ;Get DOS config
  4427. check_os_exit:
  4428.         ret
  4429. check_os    endp
  4430.  
  4431. ;--------------------------------------------------------------------
  4432. ; GET SYS SIZE - Computes the number of consecutive clusters assigned
  4433. ;                to the system files at the beginning of the disk.
  4434. ; Entry: AL - Type of operating system loaded:
  4435. ;             0 - PC DOS     1 - MS DOS
  4436. ;     The Boot record for the desired disk must be in the data
  4437. ;        buffer.
  4438. ; Exit:  AX - DOS System file configuration:
  4439. ;             20 = Consec files, sectors
  4440. ;             30 = IO.SYS consec. MSDOS.SYS not consec
  4441. ;             40 = IO.SYS not consec
  4442. ;        CX - Number of consecutive clusters
  4443. ;        DX - Number of consecutive clusters used by IO.SYS
  4444. ;        CF - Set on error
  4445. ;--------------------------------------------------------------------
  4446. sys_size_os    db    0
  4447. sys_size_bio    dw    0
  4448. sys_size_dos    dw    0
  4449.  
  4450. get_sys_size    proc    near
  4451.         push    bp
  4452.         mov     sys_size_os,al
  4453.         call    get_disk_ptrs        ;Compute disk pointers.
  4454.             mov     dx,word ptr root_pointer
  4455.             mov     si,word ptr root_pointer[2]
  4456.         mov    cx,1            ;Read only one sector of root        
  4457.         lds    bx,databuff_ptr     ;Use buffer past boot rec
  4458.         add    bx,512            
  4459.         mov    al,cs:drive_letter
  4460.         call    read_absolute        ;Read 1st part of root dir
  4461.         mov    di,offset ibmbio_name
  4462.         cmp    cs:sys_size_os,0    ;Get proper system file names
  4463.         je    get_sys_size_2        ;  for DOS.
  4464.         mov    di,offset iosys_name
  4465. get_sys_size_2:
  4466.         mov    si,bx            ;Copy ptr to start of root
  4467.         mov    cx,11
  4468.         repe    cmpsb            ;See if first file is IO.SYS
  4469.         je    get_sys_size_3
  4470. get_sys_size_err:
  4471.         stc
  4472.         jmp    get_sys_size_exit1
  4473. get_sys_size_3:
  4474.         mov    ax,[bx+1ah]        ;Get starting cluster
  4475.         cmp    ax,2            ;See if starts in 1st cluster    
  4476.         je    get_sys_size_4    
  4477.         xor    dx,dx            ;No free clusters
  4478.         xor    cx,cx    
  4479.         mov    ax,50h
  4480.         jmp    get_sys_size_exit1
  4481. get_sys_size_4:
  4482.         mov    cs:sys_size_bio,ax    
  4483.         add    si,21
  4484.         mov    cx,11
  4485.         repe    cmpsb            ;See if 2nd file is MSDOS.SYS
  4486.         jne    get_sys_size_err
  4487.         mov    ax,[bx+3ah]        ;Get starting cluster
  4488.         mov    cs:sys_size_dos,ax
  4489.  
  4490.         mov    dx,word ptr cs:fat_pointer
  4491.         mov    si,word ptr cs:fat_pointer[2]
  4492.         mov    al,cs:drive_letter
  4493.         mov    cx,4            ;Read four sectors
  4494.         call    read_absolute        ;Read FAT
  4495.         mov    ax,ds
  4496.         push    cs
  4497.         pop    ds
  4498.         push    fat_seg_low        ;Save FAT ptr for installed
  4499.         add    ax,20h            ;  code.
  4500.         mov    fat_seg_low,ax        ;Point to loaded FAT table
  4501.         mov    bx,sys_size_bio
  4502.         mov    bp,offset temp_buff    
  4503.         call    get_fat_chain        ;Get consec clusters
  4504.         pushf
  4505.         xor    ax,ax        
  4506.         mov    al,sec_per_cluster    ;Convert cluster count into
  4507.         mul    cx            ;  sector count
  4508.         mov    di,ax
  4509.         xchg    cx,ax
  4510.         popf
  4511.         mov    ax,40h
  4512.         jc    get_sys_size_exit    ;If non-consecutive, DOS 4
  4513.  
  4514.         inc    bx
  4515.         mov    si,bx            ;Save ending cluster
  4516.         mov    bx,sys_size_dos
  4517.         cmp    si,bx            ;If IO.SYS and MSDOS.SYS are
  4518.         mov    ax,30h            ;  not consecutive, DOS 3.
  4519.         jne    get_sys_size_exit
  4520.         call    get_fat_chain
  4521.         pushf    
  4522.         xor    ax,ax            ;Convert cluster count into
  4523.         mov    al,sec_per_cluster    ;  sector count.
  4524.         mul    cx
  4525.         mov    cx,ax
  4526.         add    cx,di            ;Add sector sizes
  4527.         mov    dx,di            ;Copy IO.SYS sector size
  4528.         popf    
  4529.         mov    ax,30h
  4530.         jc    get_sys_size_exit
  4531.         mov    ax,20h            ;Both consecutive, DOS 2
  4532. get_sys_size_exit:    
  4533.         push    ax
  4534.         xchg    ax,dx
  4535.         cwd
  4536.         div    targ_sec_per_cluster    ;Convert sectors to clusters
  4537.         or    dx,dx            ;  on target disk.
  4538.         je    get_sys_size_e1
  4539.         inc    ax
  4540. get_sys_size_e1:
  4541.         push    ax
  4542.         xchg    ax,cx
  4543.         cwd
  4544.         div    targ_sec_per_cluster
  4545.         or    dx,dx
  4546.         je    get_sys_size_e2
  4547.         inc    ax
  4548. get_sys_size_e2:
  4549.         xchg    ax,cx
  4550.         pop    dx
  4551.         pop    ax
  4552.         pop     fat_seg_low
  4553.         clc
  4554. get_sys_size_exit1:    
  4555.         push    cs
  4556.         pop    ds
  4557.         pop    bp
  4558.         ret
  4559. get_sys_size    endp
  4560.  
  4561. ;--------------------------------------------------------------------
  4562. ; FIXUP FAT - Removes the bad cluster entries placed by the boot 
  4563. ;             extension prog.
  4564. ; Entry: Boot sector loaded in the 1st 512 bytes of the data buffer.
  4565. ; Exit:  CF - Set if error
  4566. ;--------------------------------------------------------------------
  4567. fixup_fat    proc    near        
  4568.         call    get_disk_ptrs
  4569.         mov    dx,word ptr cs:fat_pointer
  4570.         mov    si,word ptr cs:fat_pointer[2]
  4571.         mov    al,cs:drive_letter
  4572.         lds    bx,databuff_ptr
  4573.         add    bx,512
  4574.         mov    cx,4            ;Read four sectors
  4575.         call    read_absolute        ;Read FAT
  4576.         jc    fixup_fat_exit
  4577.         mov    ax,ds
  4578.         push    cs
  4579.         pop    ds
  4580.         push    fat_seg_low        ;Save FAT ptr for installed
  4581.         add    ax,20h            ;  code.
  4582.         mov    fat_seg_low,ax        ;Point to loaded FAT table
  4583.         call    clean_fat        ;Remove bad cluster flags
  4584.         pop     fat_seg_low        ;Restore FAT segment 
  4585.  
  4586.         push    ds
  4587.         lds    bx,databuff_ptr        ;Write FAT table to disk
  4588.         add    bx,512
  4589.         mov    dx,word ptr cs:fat_pointer    ;Write FAT tables
  4590.         mov    si,word ptr cs:fat_pointer[2]
  4591.         xor    cx,cx
  4592.         mov    bp,cx
  4593.         mov    cl,ds:number_of_fats
  4594. fixup_fat_1:
  4595.         push    cx
  4596.         mov    al,cs:drive_letter
  4597.         mov    cx,4            ;Write four sectors
  4598.         call    write_absolute        ;Write FAT        
  4599.         pop    cx
  4600.         jc    fixup_fat_2
  4601.         add    dx,ds:sec_per_fat    ;Point to next FAT
  4602.         adc    si,0
  4603.         loop    fixup_fat_1
  4604. fixup_fat_2:
  4605.         pop    ds
  4606. fixup_fat_exit:
  4607.         ret
  4608. fixup_fat    endp
  4609.  
  4610. ;--------------------------------------------------------------------
  4611. ; GET DISK PTRS - Computes the logical sector numbers of the FAT and
  4612. ;                 root directorys.
  4613. ; Entry: Boot sectors loaded in the 1st 512 bytes of the data buffer.
  4614. ; Exit:  CF - Set if error
  4615. ;--------------------------------------------------------------------
  4616. fat_pointer    dd    0
  4617. root_pointer    dd    0
  4618. get_disk_ptrs    proc    near
  4619.         push    bp
  4620.         push    ds
  4621.         push    cs
  4622.         pop    es
  4623.         lds    si,databuff_ptr        ;Copy the BPB from the 
  4624.         mov    di,offset temp_buff    ;  boot record.    
  4625.         mov    bp,di
  4626.         mov    cx,40
  4627.         rep    movsb
  4628.         pop    ds
  4629.  
  4630.         call    get_fattype        ;See if FAT 12 or 16 bit
  4631.         xor    ax,ax
  4632.             mov     al,number_of_fats       ;Compute the sector of the
  4633.             mul     sec_per_fat             ;  root directory and FAT
  4634.             mov     dx,reserved_sec        ;  table.
  4635.         xor    si,si
  4636.             mov     word ptr fat_pointer,dx
  4637.             mov     word ptr fat_pointer[2],si
  4638.             add     dx,ax            ;Add size of FAT to get ptr
  4639.             adc     si,0            ;  to root directory
  4640.             mov     word ptr root_pointer,dx
  4641.             mov     word ptr root_pointer[2],si
  4642.         pop    bp
  4643.         ret
  4644. get_disk_ptrs    endp
  4645.  
  4646. ;--------------------------------------------------------------------
  4647. ; FIND FIRST - Searches the disk for a file.
  4648. ; Entry: SI - Pointer to an 8.3 filename
  4649. ; Exit:  CF - Clear if found
  4650. ;
  4651. ; FIND FIRST1 - Searches the disk for a file.
  4652. ; Entry: SI - Pointer to an ASCIIZ filename
  4653. ; Exit:  CF - Clear if found
  4654. ;--------------------------------------------------------------------
  4655. find_first    proc    near
  4656.             call    make_filename           ;Convert to ASCIIZ filename
  4657.         mov     si,dx
  4658. find_first1:
  4659.             mov     ah,1ah                  ;Insure that DTA set to
  4660.             mov     dx,DTA_OFFSET           ;  empty space in PSP
  4661.             int     21h
  4662.  
  4663.         push    cx
  4664.             mov    dx,si
  4665.             mov     ah,4eh                  ;Find file
  4666.             mov     cx,6             ;Inc system and hidden files
  4667.         int    21h
  4668.         pop    cx
  4669.         ret
  4670. find_first       endp
  4671.  
  4672. ;--------------------------------------------------------------------
  4673. ; FIND FILENAME - Searches a loaded boot record for a filename
  4674. ; Entry: DI - Pointer to 8.3 filename
  4675. ; Exit:  CF - Clear if found
  4676. ;--------------------------------------------------------------------
  4677. find_filename    proc    near
  4678.         push    di
  4679.         push    ds
  4680.             lds     si,databuff_ptr         ;Search boot record for  
  4681.             mov     bx,11                   ;  the filename pointed
  4682.             mov     cx,512            ;  to by DI.
  4683.             call    find_string
  4684.             pop     ds
  4685.         pop    di
  4686.         ret
  4687. find_filename    endp
  4688.  
  4689. ;--------------------------------------------------------------------
  4690. ; FIND STRING - Searches a buffer for a specified string
  4691. ; Entry: DS:SI - Pointer to buffer
  4692. ;        ES:DI - Pointer to string to find
  4693. ;           BX - Length of string
  4694. ;           CX - Length of buffer
  4695. ;--------------------------------------------------------------------
  4696. find_string     proc    near
  4697.         push    bp
  4698.             push    dx
  4699.             mov     bp,si                   ;Compute end of buffer
  4700.             add     bp,cx
  4701.             mov     dx,di                   ;Save ptr to string
  4702. find_string_1:
  4703.             mov     di,dx                   ;Get ptr to string
  4704.             mov     ax,si
  4705.             mov     cx,bx                   ;Get length of string
  4706.             repe    cmpsb                   ;Check string
  4707.             je      find_string_exit
  4708.             mov     si,ax
  4709.             inc     si                      ;Point to next char in buffer
  4710.             lea     di,[si+bx]              ;Determine if we are at the
  4711.             cmp     di,bp                   ;  end of the buffer.
  4712.             jbe     find_string_1
  4713.             stc
  4714. find_string_exit:
  4715.             pop     dx
  4716.         pop    bp
  4717.             ret
  4718. find_string     endp
  4719.  
  4720. ;--------------------------------------------------------------------
  4721. ; SET CRIT VEC - Sets the critical error vector to an internal routine
  4722. ;                to avoid the abort, retry, ignore message.
  4723. ;--------------------------------------------------------------------
  4724. set_crit_vec    proc    near
  4725.         push    ax
  4726.         push    bx
  4727.         push    dx
  4728.         push    ds
  4729.         push    es
  4730.             mov     ax,3524h                ;Get crititcal error vector
  4731.             int     21h                      
  4732.             mov     word ptr crit_vec,bx    ;Save vector
  4733.         push    cs
  4734.         pop    ds
  4735.         mov    word ptr crit_vec[2],es
  4736.             mov     dx,offset crit_error    ;Set to internal routine.
  4737.             mov     ax,2524h                
  4738.             int     21h
  4739.         pop    es
  4740.         pop    ds
  4741.         pop    dx
  4742.         pop    bx
  4743.         pop    ax
  4744.         ret
  4745. set_crit_vec    endp
  4746.  
  4747. ;--------------------------------------------------------------------
  4748. ; RESET CRIT VEC - Resets the critical error vector to its original
  4749. ;                  state.
  4750. ;--------------------------------------------------------------------
  4751. reset_crit_vec    proc    near
  4752.         pushf
  4753.         push    ax
  4754.         push    dx
  4755.         push    ds
  4756.             lds     dx,crit_vec             ;Get old vector
  4757.             mov     ax,2524h                ;Set vector
  4758.             int     21h
  4759.         pop    ds
  4760.         pop    dx
  4761.         pop    ax
  4762.         popf
  4763.         ret
  4764. reset_crit_vec    endp
  4765.  
  4766. ;--------------------------------------------------------------------
  4767. ; SET CTLC VEC - Sets the control C vector to an internal routine
  4768. ;                to handle the problem in a polite manner.
  4769. ;--------------------------------------------------------------------
  4770. set_ctlc_vec    proc    near
  4771.         push    ax
  4772.         push    bx
  4773.         push    dx
  4774.         push    ds
  4775.         push    es
  4776.             mov     ax,3523h                ;Get ctl-c vector
  4777.             int     21h                      
  4778.             mov     word ptr ctlc_vec,bx    ;Save vector
  4779.         push    cs
  4780.         pop    ds
  4781.         mov    word ptr ctlc_vec[2],es
  4782.             mov     dx,offset ctlc_error    ;Set to internal routine.
  4783.             mov     ax,2523h                
  4784.             int     21h
  4785.         pop    es
  4786.         pop    ds
  4787.         pop    dx
  4788.         pop    bx
  4789.         pop    ax
  4790.         ret
  4791. set_ctlc_vec    endp
  4792.  
  4793. ;--------------------------------------------------------------------
  4794. ; RESET CTLC VEC - Resets the control C vector to its original
  4795. ;                  state.
  4796. ;--------------------------------------------------------------------
  4797. reset_ctlc_vec    proc    near
  4798.         push    dx
  4799.         push    ds
  4800.             lds     dx,ctlc_vec             ;Get old vector
  4801.             mov     ax,2523h                ;Set vector
  4802.             int     21h
  4803.         pop    ds
  4804.         pop    dx
  4805.         ret
  4806. reset_ctlc_vec    endp
  4807.  
  4808. ;--------------------------------------------------------------------
  4809. ; CHK MBOOT DISK - Reads the time stamp from the installed mboot.sys
  4810. ;                  code to verify proper disk is in drive.
  4811. ;--------------------------------------------------------------------
  4812. chk_mboot_disk    proc    near
  4813.         push    ax
  4814.         push    cx
  4815.         push    dx
  4816.         cmp    installed_flag,0    ;If not installed, skip    
  4817.         je    chk_mboot_disk_exit    ;  check.
  4818.             mov     si,offset mboot_name    ;Open the MBOOT.SYS file to
  4819.             call    make_filename           ;  read the time stamp.
  4820.             mov     ax,3d00h
  4821.             int     21h
  4822.             jc      chk_mboot_disk_exit
  4823.  
  4824.         mov    bx,ax            ;Copy file handle
  4825.         mov    ax,4200h        ;Move file ptr 
  4826.         mov    dx,inst_data_ptr    
  4827.         add    dx,offset time_stamp - offset boot_data1
  4828.         xor    cx,cx
  4829.         int    21h
  4830.  
  4831.             mov     ah,3fh                  ;Read time stamp
  4832.             mov     dx,offset temp_buff
  4833.             mov     cx,4
  4834.             int     21h
  4835.  
  4836.         mov    ah,3eh            ;Close file
  4837.         int    21h
  4838.  
  4839.         mov    cx,word ptr temp_buff    ;Compare time stamps
  4840.         mov    dx,word ptr temp_buff[2]
  4841.         cmp    cx,word ptr time_stamp
  4842.         jne    chk_mboot_disk_error
  4843.         cmp    dx,word ptr time_stamp[2]
  4844.         je    chk_mboot_disk_exit
  4845. chk_mboot_disk_error:
  4846.         stc
  4847. chk_mboot_disk_exit:
  4848.         pop    dx
  4849.         pop    cx
  4850.         pop    ax
  4851.         ret
  4852. chk_mboot_disk    endp
  4853.  
  4854. ;--------------------------------------------------------------------
  4855. ; DISP SETTINGS - Displays settings for all sessions.
  4856. ; Entry: DI - Pointer to first entry data
  4857. ;        DH - Row to start display
  4858. ;--------------------------------------------------------------------
  4859. disp_settings   proc    near
  4860.             mov     dx,0806h                ;Write header.
  4861.             mov     si,offset inst_text1
  4862.             call    write_line_at           ;Write string
  4863.             add     dh,2
  4864.             mov     cx,4                    ;4 Sessions
  4865.             mov     bh,1                    ;Set session counter
  4866. disp_settings_1:
  4867.             push    di
  4868.             mov     al,bh                   ;Print session number
  4869.             mov     dl,2
  4870.             call    printnum                ;Write number
  4871.  
  4872.             mov     dl,5
  4873.             cmp     byte ptr [di+OSTYPE_OFFSET],0 ;See if session disabled
  4874.             jne     disp_settings_2
  4875.             mov     si,offset unused_text   ;Point to unused string
  4876.             call    write_line_at           ;Write string
  4877.             jmp     short disp_settings_3
  4878. disp_settings_2:
  4879.             call    disp_session
  4880.             cmp     bh,boot_default         ;If this selection is the
  4881.             jne     disp_settings_3         ;  default selection, print
  4882.             mov     dl,74                   ;  default indication.
  4883.             mov     si,offset default_str
  4884.             call    write_line_at           ;Write string
  4885. disp_settings_3:
  4886.             pop     di
  4887.             add     di,NEXT_ENTRY
  4888.             inc     dh                      ;Next row
  4889.             inc     bh                      ;Next number
  4890.             loop    disp_settings_1
  4891.             ret
  4892. disp_settings   endp
  4893.  
  4894. ;--------------------------------------------------------------------
  4895. ; DISP SESSION - Displays settings for one entry.
  4896. ; Entry: DI - Pointer to entry data
  4897. ;        DH - Row to start display
  4898. ;--------------------------------------------------------------------
  4899. disp_session    proc    near
  4900.         push    bx
  4901.             push    cx
  4902.             push    dx
  4903.         push    bp
  4904.             mov     bp,di                   ;Copy pointer to data
  4905.  
  4906.             mov     dl,5                    ;Set starting column
  4907.             mov     si,bp                   ;Get ptr to name
  4908.         cmp    byte ptr [si],80h    ;If unused, don't print
  4909.         jae    disp_session_1
  4910.             call    write_line_at           ;Write string
  4911.  
  4912.             lea     si,[bp+AUTO_OFFSET]     ;Get ptr to autoexec name
  4913.             mov     dl,29
  4914.             call    print_fn                ;Print AUTOEXEC name
  4915.  
  4916.             mov     dl,46
  4917.             lea     si,[bp+CONFIG_OFFSET]   ;Get ptr to config name
  4918.             call    print_fn                ;Print CONFIG name
  4919.  
  4920.             xor     bx,bx                   ;Get op sys type.  If not
  4921.             or      bl,[bp+OSTYPE_OFFSET]   ;  defined, don't print.
  4922.             jz      disp_session_1
  4923.         call    get_os_entry        ;Get offset into os table
  4924.         mov    si,di
  4925.             mov     di,offset key_buffer    ;First copy to buffer, then
  4926.             push    di                      ;  terminate string with zero.
  4927.             mov     cx,8
  4928.             rep     movsb
  4929.             mov     byte ptr [di],0
  4930.             pop     si
  4931.             mov     dl,63
  4932.             call    write_line_at           ;Write string
  4933. disp_session_1:
  4934.         pop    bp
  4935.             pop     dx
  4936.             pop     cx
  4937.         pop    bx
  4938.             ret
  4939. disp_session    endp
  4940.  
  4941. ;--------------------------------------------------------------------
  4942. ; MSG BOX - Displays a string and prompts the user for a Yes/No answer.
  4943. ; Entry: SI - Pointer to string. 1st two bytes are the cursor location.
  4944. ; Exit:  BL - User response, 1 = yes, 2 = no.
  4945. ;--------------------------------------------------------------------
  4946. msg_box         proc    near
  4947.         push    bp
  4948.             push    ax
  4949.             call    write_linenorm          ;Write prompt string
  4950.             pop     ax
  4951.             mov     bp,offset yesno_menu    ;Yes / No menu.
  4952.             mov     [bp+MENU_SELECTED],al   ;Set default
  4953.             call    menu
  4954.             mov     cx,1000h                ;Clear yes/no menu.
  4955.             mov     dx,1980h
  4956.             call    scroll_block
  4957.         pop    bp
  4958.             ret
  4959. msg_box         endp
  4960.  
  4961. ;--------------------------------------------------------------------
  4962. ; CONFIRM QUIT - Asks the user to confirm quit request.
  4963. ; Exit:  ZF - Set, quit confirmed.
  4964. ;--------------------------------------------------------------------
  4965. confirm_quit    proc    near
  4966.             mov     cx,1000h                ;Make room for question
  4967.             mov     dx,1980h
  4968.             call    scroll_block
  4969.         mov    si,offset confirm_msg
  4970.         mov    al,2            ;Set default to No.
  4971.         call    msg_box
  4972.         cmp    bl,1            ;See if answer Yes.
  4973.             ret
  4974. confirm_quit    endp
  4975.  
  4976. ;--------------------------------------------------------------------
  4977. ; GET NUMBER - Querys the user for a number.
  4978. ; Entry: AL - Number of characters allowed.
  4979. ;        DX - Cursor location for entry box.
  4980. ; Exit:  AX - Number returned by the user entered.
  4981. ;        CF - Set if user returned an invalid number.
  4982. ;--------------------------------------------------------------------
  4983. get_number      proc    near
  4984.             call    entry_box
  4985.         jc    get_number_exit
  4986.  
  4987.             xor     ax,ax                   ;Convert ascii number into
  4988.             xor     dx,dx                   ;  hex.
  4989.             mov     si,10                   ;Base 10
  4990. get_number_loop:
  4991.             mul     si                      ;Mul current num by base
  4992.             mov     dl,[bx]                 ;Get character
  4993.             sub     dl,30h                  ;Convert to hex from ASCII
  4994.             jb      get_number_err
  4995.             cmp     dl,9
  4996.             ja      get_number_err
  4997.             add     ax,dx                   ;Add to total.
  4998.             inc     bx                      ;Move to next char
  4999.             loop    get_number_loop
  5000.             clc
  5001. get_number_exit:
  5002.             ret
  5003. get_number_err:
  5004.             stc
  5005.             jmp     short get_number_exit
  5006. get_number      endp
  5007.  
  5008. ;-----------------------------------------------------------------------------
  5009. ; CTLC ERROR - Ctl-C routine to allow polite control C action.
  5010. ;-----------------------------------------------------------------------------
  5011. ctlc_error      proc    far
  5012.         cmp    ctlc_return,0
  5013.         je    ctlc_1
  5014.         mov    sp,ctlc_stack
  5015.         jmp    [ctlc_return]
  5016. ctlc_1:
  5017.         iret
  5018. ctlc_error      endp
  5019.  
  5020. ;--------------------------------------------------------------------
  5021. ; ENTRY BOX - Querys user for one line of input.
  5022. ; Entry: AL - Number of characters allowed.
  5023. ;        DX - Cursor location for entry box.
  5024. ; Exit:  BX - Pointer to buffer containing the user response.
  5025. ;        CX - length of response.
  5026. ;--------------------------------------------------------------------
  5027. entry_box       proc    near
  5028.             push    ax
  5029.             xor     bx,bx
  5030.             mov     ah,2                    ;Set cursor position
  5031.             call    vidint
  5032.             pop     ax
  5033.             mov     bx,offset key_buffer
  5034.             inc     al
  5035.             mov     [bx],al                 ;Set buffer size
  5036.             mov     dx,bx
  5037.         mov    ax,offset entry_box_error
  5038.         mov    ctlc_stack,sp
  5039.         mov    ctlc_return,ax
  5040.             mov     ah,0ah                  ;DOS buffered read
  5041.             int     21h
  5042.             inc     bx                      ;Point to length of string
  5043.             xor     cx,cx
  5044.             or      cl,[bx]                 ;Get length of string
  5045.             inc     bx                      ;Point to string.
  5046.         clc
  5047. entry_box_1:
  5048.         mov    ctlc_stack,0
  5049.         mov    ctlc_return,0
  5050.             ret
  5051. entry_box_error:
  5052.         mov    byte ptr [bx+1],0
  5053.         xor    cx,cx
  5054.         inc    bx
  5055.         stc
  5056.         jmp    entry_box_1
  5057. entry_box       endp
  5058.  
  5059. ;--------------------------------------------------------------------
  5060. ; SCAN4TERM - Checks to see if a character is a filename terminator.
  5061. ; Entry: AL - character
  5062. ; Exit:  ZF - Set if terminator.
  5063. ;--------------------------------------------------------------------
  5064. term_chars      db      ".:;,=+/",22h,"[]|<> ",9,13,0 ;Filename term. chars
  5065. term_chars_end  =       $
  5066.  
  5067. scan4term       proc    near
  5068.             push    cx
  5069.             push    di
  5070.             mov     cx,offset term_chars_end - offset term_chars
  5071.             mov     di,offset term_chars
  5072.             repne   scasb                   ;See if char is a terminator
  5073.             pop     di
  5074.             pop     cx
  5075.             ret
  5076. scan4term       endp
  5077.  
  5078. ;--------------------------------------------------------------------
  5079. ; CAPS CHAR - capitalizes a character
  5080. ; Entry: AL - character
  5081. ;--------------------------------------------------------------------
  5082. caps_char       proc    near
  5083.             cmp     al,"a"
  5084.             jb      caps1
  5085.             cmp     al,"z"
  5086.             ja      caps1
  5087.             and     al,0dfh
  5088. caps1:
  5089.             ret
  5090. caps_char       endp
  5091.  
  5092. ;--------------------------------------------------------------------
  5093. ; ASCIIZ2FN - Converts a filename in ASCIIZ format to 8.3 format
  5094. ; Entry: SI - Pointer to filename
  5095. ;        DI - Pointer to buffer to store the 8.3 string.
  5096. ; Exit:  SI - Pointer to 8.3 name.
  5097. ;--------------------------------------------------------------------
  5098. asciiz2fn       proc    near
  5099.             push    bx
  5100.             push    di
  5101.         push    di
  5102.         push    di
  5103.         mov    cx,11            ;Fill destination buffer
  5104.         mov    al," "            ;  with blanks.
  5105.         rep    stosb
  5106.         pop    di
  5107.             mov     bx,di                   ;Save ptr to buffer
  5108.         mov    cx,8
  5109.         add    bx,cx            ;BX = ptr to ext
  5110. asciiz2fn_1:    
  5111.         lodsb                ;Read each character in the
  5112.         cmp    al,"."            ;  name.  If '.' then jmp
  5113.         je    asciiz2fn_ext        ;  to code for ext.  If term
  5114.         call    scan4term        ;  char, end filename, else
  5115.         je    asciiz2fn_exit        ;  write the char in the dest
  5116.         call    caps_char        ;  buffer.
  5117.         stosb
  5118.         loop    asciiz2fn_1
  5119. asciiz2fn_3:
  5120.         lodsb                ;If > 8 characters, scan until
  5121.         cmp    al,"."            ;  '.' or end of string.
  5122.         je    asciiz2fn_ext
  5123.         call    scan4term
  5124.         je    asciiz2fn_exit
  5125.         jmp    short asciiz2fn_3
  5126. asciiz2fn_ext:
  5127.         mov    di,bx            ;Get ptr to ext
  5128.         mov    cx,3            
  5129. asciiz2fn_4:
  5130.         lodsb                ;Save the ext just like the
  5131.         call    scan4term        ;  filename.
  5132.         je    asciiz2fn_exit
  5133.         call    caps_char
  5134.         stosb
  5135.         loop    asciiz2fn_4
  5136. asciiz2fn_exit:
  5137.         pop    si
  5138.         pop    di
  5139.         pop    bx
  5140.         ret
  5141. asciiz2fn    endp
  5142.  
  5143. ;--------------------------------------------------------------------
  5144. ; FN2ASCIIZ - Converts a filename in 8.3 format to ASCIIZ
  5145. ; Entry: SI - Pointer to filename
  5146. ;        DI - Pointer to buffer to store the ASCIIZ string.
  5147. ; Exit:  SI - Pointer to ASCIIZ name.
  5148. ;        CX - Length of string
  5149. ;--------------------------------------------------------------------
  5150. fn2asciiz       proc    near
  5151.             push    bx
  5152.             push    dx
  5153.             push    di                      ;Save ptr to destination
  5154.             mov     bx,si
  5155.             mov     cx,8
  5156.             xor     dx,dx                   ;Clear count
  5157. fn2asciiz_1:
  5158.             lodsb
  5159.             cmp     al," "                  ;See if space
  5160.             je      fn2asciiz_2             ;If so, end of filename
  5161.             jb      fn2asciiz_4             ;If ctl char, no ext.
  5162.             stosb
  5163.             inc     dx
  5164.             loop    fn2asciiz_1
  5165. fn2asciiz_2:
  5166.             mov     si,bx                   ;Compute ptr to ext.
  5167.             add     si,8
  5168.             mov     al,"."
  5169.             stosb
  5170.             inc     dx
  5171.             mov     cx,3
  5172. fn2asciiz_3:
  5173.             lodsb
  5174.             cmp     al," "                  ;See if space
  5175.             jbe     fn2asciiz_4             ;If so, end of ext
  5176.             stosb
  5177.             inc     dx
  5178.             loop    fn2asciiz_3
  5179. fn2asciiz_4:
  5180.             xor     al,al                   ;Terminate string with zero
  5181.             stosb
  5182.             mov     cx,dx                   ;Copy count
  5183.             pop     si                      ;Get ptr to filename start
  5184.             pop     dx
  5185.             pop     bx
  5186.             ret
  5187. fn2asciiz       endp
  5188.  
  5189. ;--------------------------------------------------------------------
  5190. ; PRINT FILENAME - Prints a filename
  5191. ; Entry: SI - Pointer to filename in 8.3 format
  5192. ;        DH - Row to start display
  5193. ;--------------------------------------------------------------------
  5194. print_fn        proc    near
  5195.             mov     di,offset key_buffer
  5196.             call    fn2asciiz
  5197.             call    write_line_at           ;Write string
  5198.             ret
  5199. print_fn        endp
  5200.  
  5201. ;-----------------------------------------------------------------------------
  5202. ; WRITE ERROR - Writes an error message to the screen.
  5203. ; Entry: SI - Ptr to error ASCIIZ message string.
  5204. ;-----------------------------------------------------------------------------
  5205. write_error     proc    near
  5206.             mov     dx,error_msg_loc        ;Get location for error
  5207.             call    clear_line              ;  message.
  5208.             call    write_line_at
  5209.             ret
  5210. write_error     endp
  5211.  
  5212. ;-----------------------------------------------------------------------------
  5213. ; CLEAR LINE - Clears a line off the screen.
  5214. ; Entry: DH - Line to clear
  5215. ;-----------------------------------------------------------------------------
  5216. clear_line      proc    near
  5217.         push    cx
  5218.             push    dx
  5219.             mov     cx,dx                   ;Copy cursor start loc
  5220.             mov     dl,80                   ;Scroll 1 line to end
  5221.             mov     cl,0
  5222.             call    scroll_block
  5223.             pop     dx
  5224.         pop    cx
  5225.             ret
  5226. clear_line      endp
  5227.  
  5228. ;-----------------------------------------------------------------------------
  5229. ; CLEAR MSG - Clears a message off the screen.
  5230. ; Entry: DH - Line to clear
  5231. ;-----------------------------------------------------------------------------
  5232. clear_msg    proc    near
  5233.             mov     cx,0800h                ;Row  8 Col  0
  5234.             mov     dx,0a50h        ;Row 10 Col 80    
  5235.         call    scroll_block
  5236.         ret
  5237. clear_msg    endp
  5238.  
  5239. end_of_code     =       $
  5240. code            ends
  5241.  
  5242. end             entry
  5243.