home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progasm / conasm.arj / CONFIG.ASM
Encoding:
Assembly Source File  |  1990-03-16  |  41.6 KB  |  994 lines

  1.                TITLE   CONFIG.ASM
  2.                PAGE    60,132
  3.  
  4. ;----------------------------------------------------------------;
  5. ;  CONFIG.CTL - Allows you to dynamically change your CONFIG.SYS ;
  6. ;  configuration at boot time.  Add DEVICE = CONFIG.CTL [m]      ;
  7. ;  to your CONFIG.SYS just ahead of the first command you wish   ;
  8. ;  to be able to modify.  m is seconds CONFIG.CTL will pause     ;
  9. ;  for a keystroke before booting normally.  m defaults to zero. ;
  10. ;  Add DEVICE = CONFIG.END after the last command you wish to be ;
  11. ;  able to modify.  CONFIG.END is a dummy device and must appear ;
  12. ;  in CONFIG.SYS in order for CONFIG.CTL to operate.             ;
  13. ;                                                                ;
  14. ;  Update 7/14/89   DOS 4 checks for XMAEM.SYS before anything   ;
  15. ;                   else and marks it with a -1.                 ;
  16. ;  Update 12/19/89  Driver name changed to ZXCVBNM to avoid      ;
  17. ;                   conflict with programs named CONFIGURE.COM   ;
  18. ;                                                                ;
  19. ;  PC Magazine - Michael J. Mefford                              ;
  20. ;----------------------------------------------------------------;
  21.  
  22. _TEXT          SEGMENT PUBLIC 'CODE'          ;********************************;
  23.                ASSUME  CS:_TEXT,DS:_TEXT      ;*                              *;
  24.                ASSUME  ES:_TEXT,SS:_TEXT      ;*  Requires MASM 2.0 or later  *;
  25.                                               ;*     Remember to EXE2BIN      *;
  26.                ORG     0H                     ;*                              *;
  27.                                               ;********************************;
  28.  
  29.  
  30. ;COPYRIGHT      DB      "CONFIG.CTL 2.0 (C) 1988 Ziff Communications Co.",CR,LF
  31. ;PROGRAMMER     DB      "PC Magazine ",BOX," Michael J. Mefford",CR,LF,CTRL_Z
  32.  
  33.  
  34. ;************* DEVICE_HEADER *************;
  35.  
  36. POINTER        DD      -1
  37. ATTRIBUTE      DW      1000000000000000B
  38. DEVICE_STAG    DW      STRATEGY
  39. DEVICE_INT     DW      INTERRUPT
  40. DEVICE_NAME    DB      "ZXCVBNM "
  41.  
  42.  
  43. CR             EQU     13
  44. LF             EQU     10
  45. CTRL_Z         EQU     26
  46. SPACE          EQU     32
  47. COMMA          EQU     44
  48. FORWARD_SLASH  EQU     47
  49. BOX            EQU     254
  50.  
  51. ;-------------------------;
  52.  
  53. REQUEST_HEADER STRUC
  54.  
  55. HEADER_LENGTH  DB      ?
  56. UNIT_CODE      DB      ?
  57. COMMAND_CODE   DB      ?
  58. STATUS         DW      ?
  59. RESERVED       DQ      ?
  60.  
  61. REQUEST_HEADER ENDS
  62.  
  63. DONE           EQU     0000000100000000B       ;Status codes.
  64. UNKNOWN_CMD    EQU     1000000000000011B
  65.  
  66. ;-------------------------;
  67.  
  68. INIT           STRUC
  69.  
  70. HEADER         DB      (TYPE REQUEST_HEADER) DUP(?)
  71. UNITS          DB      ?
  72. ENDING_OFFSET  DW      ?
  73. ENDING_SEGMENT DW      ?
  74. ARGUMENTS_OFF  DW      ?
  75. ARGUMENTS_SEG  DW      ?
  76.  
  77. INIT           ENDS
  78.  
  79. REQUEST_OFFSET DW      ?
  80. REQUEST_SEG    DW      ?
  81.  
  82. ;              CODE AREA
  83. ;              ---------
  84.  
  85. ;-----------------------------------------------------------------------------;
  86. ; The only task of the strategy is to save the pointer to the request header. ;
  87. ;-----------------------------------------------------------------------------;
  88.  
  89. STRATEGY       PROC    FAR
  90.  
  91.                MOV     CS:REQUEST_OFFSET,BX    ;Request header address is
  92.                MOV     CS:REQUEST_SEG,ES       ; passed in ES:BX.
  93.                RET
  94.  
  95. STRATEGY       ENDP
  96.  
  97. ;------------------------------------------------------------------------;
  98. ; The interrupt procedure will be called immediately after the strategy. ;
  99. ;------------------------------------------------------------------------;
  100.  
  101. INTERRUPT      PROC    FAR
  102.  
  103.                PUSH    AX                      ;Responsible for all registers.
  104.                PUSH    BX
  105.                PUSH    CX
  106.                PUSH    DX
  107.                PUSH    DS
  108.                PUSHF
  109.  
  110.                MOV     DS,CS:REQUEST_SEG       ;Retrieve request header pointer.
  111.                MOV     BX,CS:REQUEST_OFFSET
  112.  
  113.                OR      STATUS[BX],DONE         ;Tell DOS we are done.
  114.                CMP     COMMAND_CODE[BX],0      ;Is it INIT command?
  115.                JZ      MAKE_STACK              ;If yes, do our stuff.
  116.                OR      STATUS[BX],UNKNOWN_CMD  ;Else, exit with confused
  117.                JMP     SHORT UNKNOWN_EXIT      ; message to DOS.
  118.  
  119. MAKE_STACK:    MOV     CX,SS                   ;Save DOS stack.
  120.                MOV     DX,SP
  121.                MOV     AX,CS
  122.                CLI
  123.                MOV     SS,AX                   ;Make new stack.
  124.                MOV     SP,0FFFEH
  125.                STI
  126.                PUSH    CX                      ;Save old stack pointers on new.
  127.                PUSH    DX
  128.  
  129.                PUSH    ES                      ;Save rest of registers.
  130.                PUSH    SI
  131.                PUSH    DI
  132.                PUSH    BP
  133.  
  134.                CALL    INITIALIZE              ;Go do our stuff.
  135.  
  136.                POP     BP                      ;Restore registers.
  137.                POP     DI
  138.                POP     SI
  139.                POP     ES
  140.  
  141.                POP     DX                      ;Restore old DOS stack.
  142.                POP     CX
  143.                CLI
  144.                MOV     SS,CX
  145.                MOV     SP,DX
  146.                STI
  147.  
  148. UNKNOWN_EXIT:  POPF                            ;Restore rest of registers.
  149.                POP     DS
  150.                POP     DX
  151.                POP     CX
  152.                POP     BX
  153.                POP     AX
  154.                RET                             ;Far return back to DOS.
  155.  
  156. INTERRUPT      ENDP
  157.  
  158. CONFIG_CTL_END LABEL   WORD
  159.  
  160. ;************* END OF RESIDENT PORTION *************;
  161.  
  162. BUFFER_SEGMENT DW      ?                       ;CONFIG.SYS buffer segment
  163. BUFFER_START   DW      ?                       ; and offset.
  164. BUFFER_END     DW      ?                       ;CONFIG.END address.
  165. END_FLAG       DB      0                       ;CONFIG.END found flag.
  166.  
  167. CONFIG_END     DB      "DCONFIG.END"
  168. CONFIG_END_LEN EQU     $ - CONFIG_END
  169.  
  170. DELAY_MSG      DB      CR,LF,LF,"Press any key if you wish to modify the "
  171.                DB      "CONFIG.SYS configuration.",CR,LF
  172.                DB      "Press Esc for quick bypass of CONFIG.CTL.",CR,LF,LF,"$"
  173. NOT_FOUND_MSG  DB      "DEVICE = CONFIG.END has to be added as a terminating "
  174.                DB      CR,LF
  175.                DB      "command in CONFIG.SYS before CONFIG.CTL can function."
  176.                DB      CR,LF
  177.                DB      "Press and key to continue.$"
  178. WRONG_VERSION  DB      "Requires DOS 2.x or greater.$"
  179.  
  180. ;--------------------------;
  181.  
  182. NORMAL         EQU     07H                     ;Screen attributes.
  183. INVERSE        EQU     70H
  184.  
  185. HEADING        LABEL   BYTE
  186.  
  187. DB "CONFIG.CTL 2.0 (C) 1988 Ziff Communications Co.",CR,LF
  188. DB "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF
  189.  
  190. DB "Press F1 to toggle active state of highlighted command.",CR,LF
  191. DB "You may optionally edit a highlighted command.",CR,LF
  192. DB "Press F2 to accept changes and exit.",CR,LF
  193. DB "Press Esc to abort changes and exit.",CR,LF
  194. DB "Note: Permanent changes are not made to the CONFIG.SYS file.$"
  195.  
  196. ;----------------------------;
  197.  
  198. STRING_MAX     EQU     80
  199. DISPLAY_MAX    EQU     67
  200. LAST_RECORD    EQU     -1
  201.  
  202. DATA_RECORD    STRUC
  203.  
  204. COMMAND        DB      STRING_MAX DUP (?)
  205. STRING_LENGTH  DW      ?
  206. ADDRESS        DW      ?                       ;Command string address start.
  207.  
  208. DATA_RECORD    ENDS
  209.  
  210. ROW_START      EQU     9
  211. COL_START      EQU     12
  212.  
  213. CODES          DB      "CBQDXFSKL1I"           ;DOS command codes.
  214. CODES_LENGTH   EQU     $ - CODES               ;For example "C" = BREAK
  215. DOS_VERSION    DB      ?
  216. DOS33          EQU     33
  217. DOS4x          EQU     4
  218.  
  219. COMMAND_TABLE  DB      "BREAK"     ,5 DUP (SPACE), "BUFFERS" ,3 DUP (SPACE)
  220.                DB      "COUNTRY"   ,3 DUP (SPACE), "DEVICE"  ,4 DUP (SPACE)
  221.                DB      "FCBS"      ,6 DUP (SPACE), "FILES"   ,5 DUP (SPACE)
  222.                DB      "SHELL"     ,5 DUP (SPACE), "STACKS"  ,4 DUP (SPACE)
  223.                DB      "LASTDRIVE" ,1 DUP (SPACE), "SWITCHES",2 DUP (SPACE)
  224. LAST_COMMAND   DB      "INSTALL"   ,3 DUP (SPACE)
  225. TABLE_END      EQU     $
  226. COMMAND_SIZE   EQU     TABLE_END - LAST_COMMAND
  227.  
  228. INACTIVE       DB      "INACTIVE" ,2 DUP (SPACE)
  229.  
  230. HIGH_BIT       EQU     10000000B
  231.  
  232. ESC_KEY        EQU     01H
  233. ENTER_KEY      EQU     1CH
  234. F1_KEY         EQU     3BH
  235. F2_KEY         EQU     3CH
  236. BACKSPACE_KEY  EQU     0EH
  237. UP_ARROW_KEY   EQU     48H
  238. DN_ARROW_KEY   EQU     50H
  239. LT_ARROW_KEY   EQU     4BH
  240. RT_ARROW_KEY   EQU     4DH
  241. HOME_KEY       EQU     47H
  242. END_KEY        EQU     4FH
  243. PG_UP_KEY      EQU     49H
  244. PG_DN_KEY      EQU     51H
  245.  
  246. BS             EQU     8
  247.  
  248. DISPATCH_KEY   DB      F1_KEY, BACKSPACE_KEY, UP_ARROW_KEY, DN_ARROW_KEY
  249.                DB      LT_ARROW_KEY, RT_ARROW_KEY, HOME_KEY, END_KEY
  250.                DB      PG_UP_KEY, PG_DN_KEY, ENTER_KEY
  251. KEY_COUNT      EQU     $ - DISPATCH_KEY
  252.  
  253. DISPATCH_TABLE DW      F1, BACKSPACE, UP_ARROW, DN_ARROW
  254.                DW      LT_ARROW, RT_ARROW, HOME, END_CURSOR
  255.                DW      PG_UP, PG_DN, DN_ARROW
  256. DISPATCH_END   EQU     $ - 2
  257.  
  258. ;              ***************
  259. ;              * SUBROUTINES *
  260. ;              ***************
  261.  
  262. ;------------------------------------------;
  263. ; INPUT                                    ;
  264. ;   DS:BX points to request header.        ;
  265. ;                                          ;
  266. ;   All registers destroyed.               ;
  267. ;------------------------------------------;
  268.  
  269.  
  270. INITIALIZE     PROC    NEAR
  271.  
  272.                MOV     ENDING_OFFSET[BX],OFFSET CONFIG_CTL_END
  273.                MOV     ENDING_SEGMENT[BX],CS   ;Resident portion setup.
  274.  
  275.                MOV     AX,ARGUMENTS_SEG[BX]    ;Retrieve CONFIG.SYS buffer
  276.                MOV     ES,AX                   ; pointers from INIT table.
  277.                MOV     BX,ARGUMENTS_OFF[BX]
  278.                PUSH    CS                      ;Point to our data.
  279.                POP     DS
  280.                MOV     BUFFER_SEGMENT,ES       ;And save the segment.
  281.                CLD
  282.  
  283.                PUSH    BX                      ;Save CONFIG.SYS buffer pointer.
  284.                MOV     AH,30H                  ;Get DOS version.
  285.                INT     21H
  286.                POP     BX                      ;Retrieve pointer.
  287.                OR      AL,AL                   ;Is it DOS 2.x or greater?
  288.                JNZ     CK_DOS3                 ;If yes, continue.
  289.                MOV     DX,OFFSET WRONG_VERSION ;Else, unsupported.
  290.                CALL    PRINT_STRING
  291.                JMP     INIT_END                ;Exit.
  292. CK_DOS3:       CMP     AL,3                    ;Is it DOS 3.x?
  293.                JNZ     CK_DOS4                 ;If no, check DOS 4.
  294.                CMP     AH,30                   ;Is it DOS 3.30?
  295.                JB      PARSE                   ;If no, done here.
  296.                MOV     DOS_VERSION,DOS33       ;Else, take note.
  297. CK_DOS4:       CMP     AL,4                    ;Is it DOS 4.x?
  298.                JB      PARSE                   ;If no, done here.
  299.                MOV     DOS_VERSION,DOS4x       ;Else, take note.
  300.  
  301. ;------------------------------------;
  302. ; Parse CONFIG.CTL second parameter. ;
  303. ;------------------------------------;
  304.  
  305. PARSE:         XOR     BP,BP                   ;Use BP to store seconds.
  306. NEXT_NUMBER:   MOV     AL,ES:[BX]              ;Retrieve a byte.
  307.                INC     BX                      ;Point to next byte.
  308.                CMP     AL,CR                   ;If carriage return of linefeed,
  309.                JZ      FIND_END                ; found end of parameter.
  310.                CMP     AL,LF
  311.                JZ      FIND_END
  312.                SUB     AL,"0"                  ;ASCII to binary.
  313.                JC      NEXT_NUMBER             ;If not between 0 and 9, skip.
  314.                CMP     AL,9
  315.                JA      NEXT_NUMBER
  316.                CBW                             ;Convert to word.
  317.                XCHG    AX,BP                   ;Swap old and new number.
  318.                MOV     CX,10                   ;Shift to left by multiplying
  319.                MUL     CX                      ; last entry by ten.
  320.                ADD     BP,AX                   ;Add new number and store in BP.
  321.                JMP     SHORT NEXT_NUMBER
  322.  
  323. ;-----------------------------------------------------------------------;
  324. ; Search for dummy CONFIG.END device as signature of end of buffer.     ;
  325. ; If found, replace "D" device code with "Z" unrecognized command code. ;
  326. ;-----------------------------------------------------------------------;
  327.  
  328. FIND_END:      MOV     BUFFER_START,BX         ;Save start of first command.
  329. NEXT_BYTE:     MOV     SI,OFFSET CONFIG_END    ;Point to CONFIG.END.
  330.                MOV     DI,BX                   ;Point to current buffer pos.
  331.                MOV     CX,CONFIG_END_LEN       ;Is it CONFIG.END?
  332.                REPZ    CMPSB
  333.                JZ      FOUND_END               ;If yes, found end.
  334.                INC     BX                          ;Else, increment buff pos.
  335.                CMP     BX,0FFFFH - CONFIG_END_LEN  ;End of segment?
  336.                JNZ     NEXT_BYTE                   ;If no, continue.
  337.                JMP     SHORT PAUSE             ;Else, give up search.
  338.  
  339. FOUND_END:     MOV     END_FLAG,1              ;Flag that we found CONFIG.END.
  340.                MOV     BYTE PTR ES:[BX],"Z"    ;"Z" out CONFIG.END command.
  341.                DEC     BX                      ;Adjust to buffer end
  342.                MOV     BUFFER_END,BX           ; and store.
  343.  
  344. ;-------------------------------------------------------------;
  345. ; See if user pressed key requesting CONFIG.SYS modification. ;
  346. ;-------------------------------------------------------------;
  347.  
  348. PAUSE:         CALL    CK_KEY                  ;Key pressed?
  349.                JNZ     ATTENTION               ;If yes, give attention.
  350.                MOV     CX,BP                   ;Else, retrieve second delay.
  351.                JCXZ    INIT_END                ;If zero, we're done.
  352.                MOV     DX,OFFSET DELAY_MSG     ;Else, display "Press key for
  353.                CALL    PRINT_STRING            ; service" message.
  354.  
  355. WAIT_A_SEC:    CALL    DELAY                   ;Delay a second.
  356. POLL_KEY:      CALL    CK_KEY                  ;Key pressed?
  357.                JNZ     ATTENTION               ;If yes, give attention.
  358.                LOOP    WAIT_A_SEC              ;Else, continue waiting until
  359.                JMP     SHORT INIT_END          ; time out.
  360.  
  361. ;--------------------------------------------------------------;
  362. ; If keystroke other than ESC was pressed and CONFIG.END dummy ;
  363. ; device found, then we're in business; otherwise exit.
  364. ;--------------------------------------------------------------;
  365.  
  366. ATTENTION:     CALL    GET_KEY                 ;Get the keystroke.
  367.                CMP     AH,ESC_KEY              ;Was is Esc?
  368.                JZ      INIT_END                ;If yes, we're done.
  369.                CMP     END_FLAG,1              ;Else, did we find CONFIG.END?
  370.                JZ      CONTINUE                ;If yes, continue.
  371.                MOV     DX,OFFSET NOT_FOUND_MSG ;Else, Display CONFIG.END not
  372.                CALL    PRINT_STRING            ; found message.
  373.                CALL    GET_KEY                 ;Wait for keystroke so it can be
  374.                JMP     SHORT INIT_END          ; read and then exit.
  375.  
  376. CONTINUE:      CALL    BUSINESS                ;Do our thing.
  377.  
  378. INIT_END:      RET                             ;Exit.
  379.  
  380. INITIALIZE     ENDP
  381.  
  382. ;--------------------------------------------;
  383. ;  INPUT                                     ;
  384. ;    DS = CS                                 ;
  385. ;    ES = CONFIG.SYS command buffer segment. ;
  386. ;                                            ;
  387. ;    All registers destroyed.                ;
  388. ;--------------------------------------------;
  389.  
  390. BUSINESS       PROC    NEAR
  391.  
  392.                CALL    CLS                     ;Clear the screen.
  393.                MOV     DX,OFFSET HEADING       ;Display heading messages.
  394.                CALL    PRINT_STRING
  395.  
  396. ;----------------------------------------------------------------------------;
  397. ; Retrieve the commands from CONFIG.SYS buffer and place them in our buffer. ;
  398. ;----------------------------------------------------------------------------;
  399.  
  400.                MOV     SI,BUFFER_START         ;Point to start of commands.
  401.                MOV     DX,BUFFER_END           ;DX = end of buffer.
  402.                MOV     BX,OFFSET DATA_STORAGE  ;Point to our storage.
  403.                PUSH    CS                      ;Destination segment our data.
  404.                POP     ES
  405.                PUSH    BUFFER_SEGMENT          ;Source segment CONFIG.SYS
  406.                POP     DS                      ; command buffer.
  407.  
  408. NEXT_COMMAND:  CMP     SI,DX                   ;End of buffer?
  409.                JAE     COMMAND_END             ;If yes, done here.
  410.                LODSB                           ;Get a byte.
  411.                CMP     AL,CR                   ;Carriage return or linefeed?
  412.                JZ      NEXT_COMMAND            ;If yes, delimiter; skip.
  413.                CMP     AL,LF
  414.                JZ      NEXT_COMMAND
  415.                PUSH    AX                      ;Else, command code character.
  416.                DEC     SI                      ;Adjust pointer.
  417.                MOV     ES:ADDRESS[BX],SI       ;Save starting address.
  418.                MOV     DI,BX                   ;Point to our storage.
  419.                CALL    RETRIEVE                ;Go retrieve the command string.
  420.                POP     AX                      ;Retrieve command code.
  421.  
  422.   ; DOS 4 checks for XMAEM.SYS before anything else and marks it with a -1
  423.   ; Added 7/14/89
  424.                CMP     AL,-1
  425.                JZ      NEXT_COMMAND
  426.  
  427.                CMP     AL,"Z"                  ;Was it unrecognized "Z" ?
  428.                JZ      NEXT_COMMAND            ;If yes, skip.
  429.                CMP     AL,"0"                  ;Was it a DOS 4 REM?
  430.                JZ      NEXT_COMMAND            ;If yes, skip.
  431.                DEC     CX                      ;Else, adjust string length.
  432.                JLE     NEXT_COMMAND            ;Null string?  If yes, skip.
  433.                MOV     ES:STRING_LENGTH[BX],CX ;Else, store length.
  434.                ADD     BX,TYPE DATA_RECORD     ;Point to next storage record.
  435.                JMP     SHORT NEXT_COMMAND      ;Get next command.
  436.  
  437. COMMAND_END:   PUSH    CS                      ;Back to our data segment.
  438.                POP     DS
  439.                MOV     COMMAND[BX],LAST_RECORD ; -1 as end of data signature.
  440.                CMP     BX,OFFSET DATA_STORAGE  ;Were there any commands?
  441.                JZ      BUSINESS_END            ;If no, done here.
  442.  
  443. ;--------------------------------------------------;
  444. ; Display the commands and let the user edit them. ;
  445. ;--------------------------------------------------;
  446.  
  447.                CALL    DISPLAY_IT
  448.                CALL    EDIT
  449.                JC      BUSINESS_END            ;If carry, Esc was pressed.
  450.  
  451. ;----------------------------------------------------------;
  452. ; Place the edited commands back in the CONFIG.SYS buffer. ;
  453. ;----------------------------------------------------------;
  454.  
  455.                MOV     BX,OFFSET DATA_STORAGE  ;Point to CONFIG.SYS buffer
  456.                PUSH    BUFFER_SEGMENT          ; as destination.
  457.                POP     ES
  458.  
  459. STORE_COMMAND: CMP     COMMAND[BX],LAST_RECORD ;Is it the last record?
  460.                JZ      BUSINESS_END            ;If yes, we're all done.
  461.                TEST    COMMAND[BX],HIGH_BIT    ;Is command inactive?
  462.                JZ      REPLACE_DATA            ;If no, OK.
  463.                MOV     COMMAND[BX],"Z"         ;Else, replace with "Z".
  464. REPLACE_DATA:  MOV     SI,BX                   ;Point to command string.
  465.                MOV     DI,ADDRESS[BX]          ;Point to destination address.
  466.                CALL    REPLACE                 ;Replace the string in buffer.
  467.                ADD     BX,TYPE DATA_RECORD     ;Point to next record.
  468.                JMP     SHORT STORE_COMMAND     ;And store it.
  469.  
  470. BUSINESS_END:  CALL    CLS                     ;Exit with clean slate.
  471.                RET
  472.  
  473. BUSINESS       ENDP
  474.  
  475. ;---------------------------------------;
  476. ; INPUT                                 ;
  477. ;   DS:SI points to CONFIG.SYS buffer.  ;
  478. ;   ES:DI points to our storage.        ;
  479. ;                                       ;
  480. ; OUTPUT                                ;
  481. ;   SI and DI at end of string.         ;
  482. ;   CX = string length include one byte ;
  483. ;   for CR or LF.  ASCIIZ is stripped.  ;
  484. ;                                       ;
  485. ;   AX  destroyed.                      ;
  486. ;---------------------------------------;
  487.  
  488. RETRIEVE       PROC    NEAR
  489.  
  490.                MOV     CX,-1                   ;Initialize counter.
  491.                LODSB                           ;Load and store code.
  492.                MOV     AH,AL                   ;Preserve code.
  493. STORE_IT:      STOSB
  494.                INC     CX
  495.                CMP     AL,CR                   ;If terminating carriage return
  496.                JZ      RETRIEVE_END            ; or linefeed, we're done.
  497.                CMP     AL,LF
  498.                JZ      RETRIEVE_END
  499. NEXT_RETRIEVE: LODSB                           ;Get a byte.
  500.                OR      AL,AL                   ;Is it ASCIIZ zero?
  501.                JNZ     STORE_IT                ;If no, check CR or LF.
  502.                CMP     BYTE PTR [SI],CR        ;Else, end of parameters?
  503.                JBE     NEXT_RETRIEVE           ;If yes, skip.
  504.                CMP     ES:DOS_VERSION,DOS33    ;Else, is it DOS 3.3?
  505.                JZ      NEXT_RETRIEVE           ;If yes, strip all zeros.
  506.                CMP     AH,"S"                  ;Else, is it SHELL ASCIIZ?
  507.                JZ      CONVERT                 ;If yes, convert to space.
  508.                CMP     AH,"D"                  ;Else, is it a DEVICE ASCIIZ?
  509.                JZ      CONVERT                 ;If yes, convert to space.
  510.                CMP     AH,"I"                  ;Else, is it INSTALL?
  511.                JNZ     NEXT_RETRIEVE           ;If no, strip.
  512. CONVERT:       MOV     AL,SPACE                ;Else, convert to space.
  513.                JMP     SHORT STORE_IT
  514. RETRIEVE_END:  RET
  515.  
  516. RETRIEVE       ENDP
  517.  
  518. ;--------------------------------------;
  519. ; INPUT                                ;
  520. ;   DS:SI points to our storage.       ;
  521. ;   ES:DI points to CONFIG.SYS buffer. ;
  522. ;   BX = current record.               ;
  523. ;                                      ;
  524. ; OUTPUT                               ;
  525. ;   ASCIIZ is reinserted in string.    ;
  526. ;   SI and DI at end of string.        ;
  527. ;                                      ;
  528. ;   AX, CX, DX, BP destroyed.          ;
  529. ;--------------------------------------;
  530.  
  531. REPLACE        PROC    NEAR
  532.  
  533.                MOV     CX,STRING_LENGTH[BX]    ;Retrieve string length.
  534.                INC     CX                      ;Include command code byte.
  535.                MOV     BP,-1                   ;ASCIIZ flag.
  536.                XOR     DX,DX                   ;Leading space flag.
  537.                MOV     AH,[SI]                 ;Retrieve code.
  538. NEXT_REPLACE:  LODSB                           ;Get a byte.
  539.                CMP     AL,"a"                  ;Capitalize.
  540.                JB      CK_LEADING
  541.                CMP     AL,"z"
  542.                JA      CK_LEADING
  543.                AND     AL,5FH
  544.  
  545. CK_LEADING:    CMP     AL,SPACE                ;Is it a leading space?
  546.                JNZ     CK_ADD_ZERO             ;If no, check if zero time.
  547.                CMP     DX,1                    ;If command only thing stored
  548.                JZ      NEXT_REPLACE            ; so far, then it's leading.
  549.  
  550. CK_ADD_ZERO:   CMP     BP,-1                   ;Have we stored a zero yet?
  551.                JNZ     CK_CR_LF                ;If yes, check CR and LF.
  552.                CMP     AL,SPACE                ;Else, is it space?
  553.                JZ      CK_DOS                  ;If yes, check of DOS 4.
  554.                CMP     AH,"Q"                  ;Is it COUNTRY?
  555.                JZ      STORE_BYTE              ;If yes, store the space.
  556.                CMP     DOS_VERSION,DOS33       ;Else, is DOS 3.3?
  557.                JNZ     STORE_BYTE              ;If no, store the non space.
  558.                CMP     AL,COMMA                ;Else, is it a comma or slash?
  559.                JZ      ASCIIZ                  ;If yes, ASCIIZ it.
  560.                CMP     AL,FORWARD_SLASH
  561.                JZ      ASCIIZ
  562.                JMP     SHORT STORE_BYTE        ;Else, just store the byte.
  563.  
  564. CK_DOS:        CMP     DOS_VERSION,DOS4x       ;Is it DOS 4?
  565.                JNZ     ASCIIZ                  ;If no, ASCIIZ.
  566.                CMP     AH,"D"                  ;Else, is it DEVICE or SHELL?
  567.                JZ      ASCIIZ                  ;If yes, ASCIIZ.
  568.                CMP     AH,"S"
  569.                JZ      ASCIIZ
  570.                CMP     AH,"I"                  ;Or INSTALL of DOS 4.
  571.                JNZ     STORE_BYTE              ;Else, just store the byte.
  572.  
  573. ASCIIZ:        XCHG    AX,BP                   ;Swap special character.
  574.                XOR     AX,AX                   ;Store the zero.
  575.                STOSB                           ;Retrieve the character and
  576.                XCHG    AX,BP                   ; zero in BP as flag.
  577.                CMP     DOS_VERSION,DOS33       ;Is it DOS 3.3?
  578.                JNZ     BYTE_STORED             ;If yes, store the char also.
  579.  
  580. CK_CR_LF:      CMP     AL,CR                   ;If CR or LF we're done here.
  581.                JZ      PAD_SPACES
  582.                CMP     AL,LF
  583.                JZ      PAD_SPACES
  584.  
  585. STORE_BYTE:    STOSB                           ;Store the byte.
  586. BYTE_STORED:   INC     DX                      ;Increment count.
  587.                LOOP    NEXT_REPLACE
  588.  
  589. PAD_SPACES:    DEC     CX                      ;Throw away CR or LF count.
  590.                JLE     CK_ZERO                 ;If end of string, done.
  591.                MOV     AL,SPACE                ;Else, move leading spaces
  592.                REP     STOSB                   ; to end of string.
  593.  
  594. CK_ZERO:       CMP     BP,-1                   ;Have we replaced a zero yet?
  595.                JNZ     REPLACE_END             ;If yes done.
  596.                CMP     DOS_VERSION,DOS4x       ;Is it DOS 4.x?
  597.                JNZ     ADD_ZERO                ;If no, add a zero.
  598.                CMP     AH,"S"                  ;Else, is it SHELL filename?
  599.                JZ      ADD_ZERO                ;If yes, ASCIIZ.
  600.                CMP     AH,"D"                  ;Else, is it DEVICE filename?
  601.                JZ      ADD_ZERO                ;If yes, ASCIIZ.
  602.                CMP     AH,"I"                  ;Else, is it INSTALL filename?
  603.                JNZ     REPLACE_END             ;If no, done
  604. ADD_ZERO:      XOR     AL,AL                   ;Else, add ASCIIZ.
  605.                STOSB
  606.  
  607. REPLACE_END:   RET
  608.  
  609. REPLACE        ENDP
  610.  
  611. ;------------------------------------------;
  612. ;   Display the commands on the screen.    ;
  613. ;   All registers destroyed.               ;
  614. ;------------------------------------------;
  615.  
  616. DISPLAY_IT     PROC    NEAR
  617.  
  618.                MOV     BP,OFFSET DATA_STORAGE  ;Point to data storage.
  619.                MOV     DH,ROW_START            ;Point to first display row.
  620.  
  621. NEXT_DISPLAY:  XOR     DL,DL                   ;Column zero.
  622.                CALL    SET_CURSOR              ;Set cursor position.
  623.                CMP     COMMAND[BP],LAST_RECORD ;Is it the last record?
  624.                JZ      DISPLAY_END             ;If yes, done here.
  625.                CALL    DECODE                  ;Else, decode the command.
  626.                MOV     AL,"="                  ;Add quotes and a space.
  627.                CALL    WRITE_TTY
  628.                MOV     AL,SPACE
  629.                CALL    WRITE_TTY
  630.                MOV     SI,BP                   ;Point to command string.
  631.                INC     SI
  632.                MOV     CX,STRING_LENGTH[BP]    ;Retrieve the string length.
  633. NEXT_ARGUMENT: LODSB                           ;Display the command.
  634.                CALL    WRITE_TTY
  635.                LOOP    NEXT_ARGUMENT
  636.                ADD     BP,TYPE DATA_RECORD     ;Point to next record.
  637.                INC     DH                      ;Next cursor row.
  638.                CMP     DH,25                   ;Is it row 25?
  639.                JNZ     NEXT_DISPLAY            ;If no, continue.
  640.  
  641. DISPLAY_END:   RET
  642.  
  643. DISPLAY_IT     ENDP
  644.  
  645. ;-----------------------------------------;
  646. ; INPUT                                   ;
  647. ;   BP points to command.                 ;
  648. ;                                         ;
  649. ; OUTPUT                                  ;
  650. ;   The command is decoded and displayed. ;
  651. ;                                         ;
  652. ;   AX, CX, SI and DI destroyed.          ;
  653. ;-----------------------------------------;
  654.  
  655. DECODE         PROC    NEAR
  656.  
  657.                MOV     SI,OFFSET INACTIVE      ;Assume command inactive.
  658.                MOV     AL,COMMAND[BP]          ;Retrieve command.
  659.                TEST    AL,HIGH_BIT             ;Is it marked inactive?
  660.                JNZ     FOUND_COMMAND           ;If yes, assumed right.
  661.                MOV     DI,OFFSET CODES         ;Else, point to codes.
  662.                MOV     CX,CODES_LENGTH         ;Number of codes.
  663.                REPNZ   SCASB                   ;Search for match.
  664.                MOV     SI,OFFSET TABLE_END     ;Point to lookup table.
  665.                INC     CX                      ;Adjust count.
  666. FIND_COMMAND:  SUB     SI,COMMAND_SIZE         ;Point to appropriate command.
  667.                LOOP    FIND_COMMAND
  668.  
  669. FOUND_COMMAND: MOV     CX,COMMAND_SIZE         ;Command string length.
  670. DISPLAY_CMD:   LODSB                           ;Display it.
  671.                CALL    WRITE_TTY
  672.                LOOP    DISPLAY_CMD
  673.                RET
  674.  
  675. DECODE         ENDP
  676.  
  677. ;----------------------------------;
  678. ;  OUTPUT                          ;
  679. ;    Carry flag = 0 if good edit.  ;
  680. ;    Carry flag = 1 if edit abort. ;
  681. ;                                  ;
  682. ;    All registers destroyed.      ;
  683. ;----------------------------------;
  684.  
  685. EDIT           PROC    NEAR
  686.  
  687.                MOV     BP,OFFSET DATA_STORAGE  ;Point to data storage.
  688.                MOV     DH,ROW_START            ;Point to first row.
  689.                MOV     BL,INVERSE              ;Highlight the first command.
  690.                CALL    HIGHLIGHT_BAR           ;Return with DI = 1; first char.
  691.  
  692. NEXT_KEY:      CALL    GET_KEY                 ;Get a keystroke.
  693.                CMP     AH,ESC_KEY              ;Is it ESC?
  694.                JZ      NO_CHANGE               ;If yes, exit with no change.
  695.                CMP     AH,F2_KEY               ;Is it F2?
  696.                JZ      EDIT_END                ;If yes, exit with changes.
  697.                CMP     AL,BS                   ;Is it backspace?
  698.                JZ      FUNCTION                ;If yes, function.
  699.                CMP     AL,CR                   ;Is it carriage return?
  700.                JZ      FUNCTION                ;If yes, function.
  701.                CMP     AH,F1_KEY               ;Is it F1 or above?
  702.                JAE     FUNCTION                ;If yes, function.
  703.  
  704. ASCII:         CMP     AL,SPACE                ;Is it space or above?
  705.                JB      NEXT_KEY                ;If no, skip.
  706.                CMP     DI,STRING_LENGTH[BP]    ;Else, are we at end of field?
  707.                JA      NEXT_KEY                ;If yes, skip.
  708.                MOV     COMMAND[BP+DI],AL       ;Else, store character.
  709.                INC     DI                      ;Point to next storage.
  710.                INC     DL                      ;Increment cursor column.
  711.                CALL    WRITE_TTY               ;Write the character to screen.
  712.                JMP     SHORT NEXT_KEY          ;Get next keystroke.
  713.  
  714. FUNCTION:      MOV     AL,AH                   ;Scan code in AL.
  715.                MOV     CX,KEY_COUNT            ;Count of active functions.
  716.                PUSH    DI                      ;Preserve DI.
  717.                MOV     DI,OFFSET DISPATCH_KEY  ;Point to active keys.
  718.                REPNZ   SCASB                   ;Scan for match.
  719.                POP     DI                      ;Retrieve DI.
  720.                JNZ     NEXT_KEY                ;If no match, next key.
  721.                MOV     SI,OFFSET DISPATCH_END  ;Else, point to dispatch table.
  722.                SHL     CX,1                    ;Convert to word offset.
  723.                SUB     SI,CX                   ;Point to appropriate procedure
  724.                CALL    DS:[SI]                 ; and go do it.
  725.                JMP     SHORT NEXT_KEY          ;Get next keystroke.
  726.  
  727. NO_CHANGE:     STC
  728. EDIT_END:      RET
  729.  
  730. EDIT           ENDP
  731.  
  732. ;----------------------------------------------------------------------------; 
  733. ; The following are the active function, arrow and backspace key procedures. ;
  734. ;----------------------------------------------------------------------------;
  735.  
  736. F1             PROC    NEAR
  737.  
  738.                PUSH    DI                      ;Preserve DI and DX.
  739.                PUSH    DX
  740.                XOR     DL,DL                   ;Column zero.
  741.                CALL    SET_CURSOR              ;Set cursor.
  742.                XOR     COMMAND[BP],HIGH_BIT    ;Toggle active state.
  743.                CALL    DECODE                  ;Decode the command.
  744.                POP     DX                      ;Restore cursor position.
  745.                CALL    SET_CURSOR
  746.                POP     DI                      ;Restore DI.
  747.                RET
  748.  
  749. F1             ENDP
  750.  
  751. ;------------------------------;
  752.  
  753. BACKSPACE      PROC    NEAR
  754.  
  755.                CMP     DI,1                    ;Are we already at first char?
  756.                JZ      BACKSPACE_END           ;If yes, skip.
  757.                DEC     DL                      ;Else, decrement cursor
  758.                DEC     DI                      ; and character storage position.
  759.                MOV     COMMAND[BP+DI],SPACE    ;Store a space.
  760.                MOV     AL,BS                   ;Write a backspace, space and
  761.                CALL    WRITE_TTY               ;backspace to screen.
  762.                MOV     AL,SPACE
  763.                CALL    WRITE_TTY
  764.                MOV     AL,BS
  765.                CALL    WRITE_TTY
  766. BACKSPACE_END: RET
  767.  
  768. BACKSPACE      ENDP
  769.  
  770. ;------------------------------;
  771.  
  772. UP_ARROW       PROC    NEAR
  773.  
  774.                CMP     BP,OFFSET DATA_STORAGE  ;Are we already at top row?
  775.                JZ      UP_ARROW_END            ;If yes, skip.
  776.                MOV     BL,NORMAL               ;Else, return to normal
  777.                CALL    HIGHLIGHT_BAR           ; attribute current row.
  778.                SUB     BP,TYPE DATA_RECORD     ;Move up a record.
  779.                DEC     DH                      ;Move cursor up one.
  780.                MOV     BL,INVERSE              ;Display line in inverse video.
  781.                CALL    HIGHLIGHT_BAR
  782. UP_ARROW_END:  RET
  783.  
  784. UP_ARROW       ENDP
  785.  
  786. ;------------------------------;
  787.  
  788. DN_ARROW       PROC    NEAR
  789.  
  790.                CMP     COMMAND[BP+TYPE DATA_RECORD],LAST_RECORD
  791.                JZ      DN_ARROW_END
  792.                CMP     DH,24                   ;If last record already or
  793.                JZ      DN_ARROW_END            ; bottom of screen, skip.
  794.                MOV     BL,NORMAL               ;Else, return current row to
  795.                CALL    HIGHLIGHT_BAR           ; normal.
  796.                ADD     BP,TYPE DATA_RECORD     ;Go down a record.
  797.                INC     DH                      ;And down a row.
  798.                MOV     BL,INVERSE              ;Display the line inverse video.
  799.                CALL    HIGHLIGHT_BAR
  800. DN_ARROW_END:  RET
  801.  
  802. DN_ARROW       ENDP
  803.  
  804. ;------------------------------;
  805.  
  806. LT_ARROW       PROC    NEAR
  807.  
  808.                CMP     DI,1                    ;Are we already first positon?
  809.                JZ      LT_ARROW_END            ;If yes, skip.
  810.                DEC     DI                      ;Else, decrement storage position
  811.                DEC     DL                      ; and cursor position.
  812.                CALL    SET_CURSOR
  813. LT_ARROW_END:  RET
  814.  
  815. LT_ARROW       ENDP
  816.  
  817. ;------------------------------;
  818.  
  819. RT_ARROW       PROC    NEAR
  820.  
  821.                CMP     DI,STRING_LENGTH[BP]    ;Are we already end of string?
  822.                JA      RT_ARROW_END            ;If yes, skip.
  823.                INC     DI                      ;Else, increment storage position
  824.                INC     DL                      ; and cursor position.
  825.                CALL    SET_CURSOR
  826. RT_ARROW_END:  RET
  827.  
  828. RT_ARROW       ENDP
  829.  
  830. ;------------------------------;
  831.  
  832. HOME           PROC    NEAR
  833.  
  834.                MOV     DI,1                    ;Home storage position
  835.                MOV     DL,COL_START            ; and cursor.
  836.                CALL    SET_CURSOR
  837.                RET
  838.  
  839. HOME           ENDP
  840.  
  841. ;------------------------------;
  842.  
  843. END_CURSOR     PROC    NEAR
  844.  
  845.                MOV     DI,STRING_LENGTH[BP]    ;Retrieve string length.
  846.                MOV     CX,DI
  847.                MOV     DL,CL
  848.                ADD     DL,COL_START            ;Add to starting column.
  849.                INC     DI                      ;Adjust.
  850.                CALL    SET_CURSOR              ;Set cursor.
  851.                RET
  852.  
  853. END_CURSOR     ENDP
  854.  
  855. ;------------------------------;
  856.  
  857. PG_DN          PROC    NEAR
  858.  
  859.                MOV     BL,NORMAL               ;Current postion back to normal.
  860.                CALL    HIGHLIGHT_BAR
  861. NEXT_PG_DN:    CMP     COMMAND[BP+TYPE DATA_RECORD],LAST_RECORD
  862.                JZ      PAGE_END
  863.                ADD     BP,TYPE DATA_RECORD     ;If not already last position,
  864.                INC     DH                      ; go to it.
  865.                JMP     SHORT NEXT_PG_DN
  866. PAGE_END:      MOV     BL,INVERSE              ;And display it in inverse video.
  867.                CALL    HIGHLIGHT_BAR
  868.                RET
  869.  
  870. PG_DN          ENDP
  871.  
  872. ;------------------------------;
  873.  
  874. PG_UP          PROC    NEAR
  875.  
  876.                MOV     BL,NORMAL               ;Restore current position to
  877.                CALL    HIGHLIGHT_BAR           ; normal.
  878.                MOV     BP,OFFSET DATA_STORAGE  ;Move to top command.
  879.                MOV     DH,ROW_START            ;And cursor position.
  880.                MOV     BL,INVERSE              ;And highlight.
  881.                CALL    HIGHLIGHT_BAR
  882.                RET
  883.  
  884. PG_UP          ENDP
  885.  
  886. ;------------------------------------------;
  887. ; INPUT                                    ;
  888. ;   BL = attribute.                        ;
  889. ;   BP points to current command.          ;
  890. ;                                          ;
  891. ; OUTPUT                                   ;
  892. ;   DI = 1 (First storage position.)       ;
  893. ;   DL = cursor column start.              ;
  894. ;                                          ;
  895. ;   CX, SI destroyed.                      ;
  896. ;------------------------------------------;
  897.  
  898. HIGHLIGHT_BAR  PROC    NEAR
  899.  
  900.                MOV     CX,STRING_LENGTH[BP]    ;Retrieve string length.
  901.                MOV     SI,BP                   ;Point to command.
  902.                INC     SI                      ;Adjust.
  903.                MOV     DL,COL_START            ;Point to first position.
  904. HIGHLIGHT:     CALL    SET_CURSOR              ;Set the cursor.
  905.                LODSB
  906.                PUSH    CX                      ;Preserve CX.
  907.                MOV     CX,1
  908.                MOV     AH,9                    ;Write char/attribute.
  909.                INT     10H
  910.                INC     DL                      ;Increment cursor postion.
  911.                POP     CX
  912.                LOOP    HIGHLIGHT
  913.                MOV     DL,COL_START            ;Point to first position again.
  914.                CALL    SET_CURSOR              ;Set cursor.
  915.                MOV     DI,1                    ;Return with DI = first storage.
  916.                RET
  917.  
  918. HIGHLIGHT_BAR  ENDP
  919.  
  920. ;---------------------------------------; 
  921. ; The following are support procedures. ;
  922. ;---------------------------------------;
  923.  
  924. WRITE_TTY      PROC    NEAR
  925.  
  926.                MOV     AH,0EH                  ;Write TTY via BIOS.
  927.                INT     10H
  928.                RET
  929.  
  930. WRITE_TTY      ENDP
  931.  
  932. ;------------------------------;
  933.  
  934. SET_CURSOR     PROC    NEAR
  935.  
  936.                XOR     BH,BH                   ;Enter with DX = cursor postion.
  937.                MOV     AH,2                    ;Set cursor position via BIOS.
  938.                INT     10H
  939.                RET
  940.  
  941. SET_CURSOR     ENDP
  942.  
  943. ;------------------------------;
  944.  
  945. CLS            PROC    NEAR
  946.  
  947.                MOV     AH,0FH                  ;Get current video mode.
  948.                INT     10H
  949.                XOR     AH,AH                   ;Set current video mode.
  950.                INT     10H                     ;Result is a clear screen.
  951.                RET
  952.  
  953. CLS            ENDP
  954.  
  955. ;------------------------------;
  956.  
  957. DELAY          PROC    NEAR
  958.  
  959.                PUSH    DS                      ;Preserve data segment.
  960.                MOV     AX,40H                  ;Point to BIOS data segment.
  961.                MOV     DS,AX
  962.                MOV     AX,DS:[6CH]             ;Retrieve timer low.
  963.                ADD     AX,18                   ;Add 18 counts per second.
  964. NEXT_COUNT:    MOV     DX,DS:[6CH]             ;Retrieve timer low.
  965.                CMP     DX,AX                   ;Have we timed out?
  966.                JNZ     NEXT_COUNT              ;If not, wait until second up.
  967.                POP     DS                      ;Restore data segment.
  968.                RET
  969.  
  970. DELAY          ENDP
  971.  
  972. ;------------------------------;
  973.  
  974. GET_KEY:       MOV     AH,0                    ;Retrieve keystroke via BIOS.
  975.                INT     16H
  976.                RET
  977.  
  978. CK_KEY:        MOV     AH,1                    ;Check for keystroke via BIOS.
  979.                INT     16H
  980.                RET
  981.  
  982. ;------------------------------;
  983.  
  984. PRINT_STRING:  MOV     AH,9                    ;Print string via DOS.
  985.                INT     21H
  986.                RET
  987.  
  988. ;------------------------------;
  989.  
  990. DATA_STORAGE   EQU     $
  991.  
  992. _TEXT          ENDS
  993.                END
  994.