home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / GLEN / STUFF30.ZIP / STUFFIT.ASM next >
Assembly Source File  |  1990-09-06  |  24KB  |  1,222 lines

  1.    PAGE 80,132
  2.    TITLE "StuffIt, Delayed keyboard stuffer. (C) Terje Mathisen 1989-90"
  3.  
  4. Version EQU 300h
  5. VerStr  EQU '3.00'
  6.  
  7.     LOCALS
  8.  
  9. TicksPrDay    EQU 1573041
  10. TicksPrHour    EQU 65543
  11.  
  12. BIOS SEGMENT AT 40h
  13.     ORG 1Ah
  14. BufferHead    dw ?
  15. BufferTail    dw ?
  16. BufferStart    dw 16 dup (?)
  17. BufferEnd    LABEL word
  18.  
  19.     ORG 49h
  20. VideoMode    db ?
  21. CrtWidth    dw ?
  22.     ORG 4Eh
  23. CurrStart    dw ?
  24. Cursor          dw ?
  25.  
  26.     ORG 6Ch
  27. BIOS_Timer    dw 2 dup (?)
  28. BIOS ENDS
  29.  
  30. BOOT SEGMENT AT 0F000h
  31.     ORG 0FFF0h
  32. RebootLocation    LABEL FAR
  33. BOOT ENDS
  34.  
  35. REBOOT_CODE     EQU 0
  36. ATTIME_CODE     EQU 1
  37. DELTATIME_CODE  EQU 2
  38. FIND_CODE       EQU 3
  39. PROMPT_CODE     EQU 4
  40. EXTENDED_CODE   EQU 255
  41. GETWORD_CODE    EQU 254
  42.  
  43. CODE SEGMENT PARA PUBLIC 'code'
  44.     ASSUME CS:CODE,DS:NOTHING,ES:NOTHING
  45.         ORG 0
  46. PspStart label byte
  47.  
  48.     ORG 5Ch
  49. ResidentSize    dw ?
  50.  
  51. ;LowStart label byte
  52.  
  53.     ORG 80h
  54. CommandLen      db ?
  55. CommandLine    LABEL BYTE
  56.  
  57.     ORG 100h
  58. start:
  59.     jmp init
  60.  
  61. Semafor    equ 'ST'                        ; Short for STuffit
  62.  
  63. LowStart label byte
  64. HighStart label byte
  65.  
  66. MoveDown EQU HighStart - LowStart
  67.  
  68. Int2F    proc far
  69.     cmp ax,0E000h
  70.      jne @@chain
  71.  
  72.     cmp dx,Semafor                  ; Be safe, insist on semafor in DX
  73.      je @@We_Are_Here
  74.  
  75. @@chain:
  76. ;    jmp [OldInt2F]
  77.     db 0EAh
  78. OldInt2F dd ?
  79.  
  80. @@We_Are_Here:
  81.     mov al,0FFh
  82.     mov dx,cs
  83.         mov bx,Version
  84.  
  85.     iret
  86.  
  87. Int2F    endp
  88.  
  89. PUSH_AX_OPCODE EQU  50h
  90. IRET_OPCODE    EQU 0CFh
  91.  
  92. MyTimer PROC FAR
  93.     pushf
  94. ;    call [OldTimer]
  95.         db 09Ah
  96. OldTimer dw ?,?
  97.  
  98. SelfModify label byte                   ; This will be IRET when idle
  99.     push ax                         ; PUSH AX = 50h, IRET = 0CFh
  100.  
  101.         inc byte ptr [cs:active-MoveDown] ;  INC from -1 to 0
  102.          jnz Already_Active
  103.  
  104.         STI
  105.     CLD
  106.  
  107.     push bx
  108.     push cx
  109.  
  110.     push dx
  111.     push si
  112.     push di
  113.     push ds
  114.     push es
  115.  
  116.     push cs
  117.     pop ds
  118.     ASSUME DS:CODE
  119.  
  120.     mov es,[BiosSeg-MoveDown]
  121.     ASSUME ES:BIOS
  122.  
  123.     call word ptr [StuffMode-MoveDown]
  124.  
  125.     pop es
  126.     pop ds
  127.     pop di
  128.     pop si
  129.     pop dx
  130.  
  131.     pop cx
  132.     pop bx
  133.  
  134.     ASSUME CS:CODE,DS:NOTHING,ES:NOTHING
  135.  
  136. Already_Active:
  137.  
  138.         CLI
  139.         dec byte ptr [cs:active-MoveDown]
  140.  
  141.      pop ax
  142.     iret
  143. MyTimer ENDP
  144.  
  145.     ASSUME CS:CODE,DS:CODE,ES:BIOS
  146.  
  147. StuffFinished:
  148.     mov [SelfModify-MoveDown],IRET_OPCODE
  149.     ret
  150.  
  151. NextKey proc near
  152.     mov si,[StuffPtr-MoveDown]
  153. GetNext:
  154.     cmp si,[StuffEnd-MoveDown]
  155.      jae StuffFinished
  156.  
  157.     lodsb
  158.     cmp al,GETWORD_CODE
  159.          ja Extended                    ; Extended function
  160.      je @@GetBoth                   ; 254 => char, scan follows
  161.  
  162.     mov ah,2            ; Simulate scan = 2 for normal chars
  163.     cmp al,224            ; Character for Enh.Kbd new keys
  164.      je @@GetScan
  165.  
  166.     or al,al
  167.      jne stuff
  168.  
  169. @@GetScan:
  170.     mov ah,[si]
  171.     inc si
  172.      jmp short stuff
  173.  
  174. @@GetBoth:
  175.     lodsw
  176. Stuff:
  177.     CLI
  178.     mov di,[BufferTail]
  179.     stos word ptr [BIOS:di]
  180.     cmp di, OFFSET BufferEnd
  181.      jb @@1
  182.     mov di, OFFSET BufferStart
  183. @@1:
  184.     cmp di,[BufferHead]
  185.      je @@Overflow
  186.     mov [BufferTail],di
  187.     STI
  188. StuffOK:
  189.     mov [StuffPtr-MoveDown],si
  190.      jmp GetNext
  191.  
  192. @@OverFlow:
  193.     STI
  194.     ret
  195. NextKey ENDP
  196.  
  197. ExtendedTable label word
  198.   dw Reboot      - MoveDown
  199.   dw AbsTime     - MoveDown
  200.   dw DeltaTime   - MoveDown
  201.   dw StartFind   - MoveDown
  202.   dw StartPrompt - MoveDown
  203.  
  204. Extended PROC near
  205.     lodsb                           ; Get function code!
  206.         cmp al,4
  207.          ja StuffFinished               ; Program Error!
  208.  
  209.         cbw
  210.         mov bx,ax
  211.         shl bx,1
  212.          jmp ExtendedTable[bx - MoveDown]
  213.  
  214. Extended endp
  215.  
  216. Reboot proc near
  217.     mov word ptr [BIOS: 72h],1234h
  218.      jmp RebootLocation
  219. Reboot endp
  220.  
  221.  
  222. AbsTime:                                ; Both Abs time & Delta time land here
  223. DeltaTime:                              ; ---- " ----
  224.  
  225. GetTime proc near
  226.  
  227.         cmp al, DELTATIME_CODE
  228.     lodsw                ; Next 3 bytes is # of ticks
  229.     mov dl,[si]
  230.          jz @@TimeOk                    ; Delta time, so wait # of ticks
  231.          
  232. ; Wait until time equal: Calculate remaining ticks
  233.  
  234.     sub ax,[Bios_Timer]
  235.     sbb dl,BYTE PTR [Bios_Timer+2]
  236.      jae @@TimeOk
  237.  
  238.     add ax,TicksPrDay AND 0FFFFh
  239.     adc dl,TicksPrDay Shr 16
  240.  
  241. @@TimeOK:
  242.     inc si
  243.     mov [StuffPtr-MoveDown],si               ; Point to next byte
  244.  
  245.         sub dh,dh                       ; Fill top of DX with 0
  246.     or ax,dx
  247.      jz @@WaitZero                  ; Special case, wait for empty kbd
  248.  
  249.     mov [CountLow-MoveDown],ax
  250.     mov [CountHigh-MoveDown],dl
  251.     mov [StuffMode-MoveDown], OFFSET CountDown - MoveDown
  252.     ret
  253.  
  254. @@WaitZero:
  255.     mov [StuffMode-MoveDown], OFFSET WaitEmpty - Movedown
  256.     ret
  257. GetTime endp
  258.  
  259. CountDown proc near
  260.     DEC [CountLow-MoveDown]
  261.      jnz NoChange
  262.     SUB [CountHigh-MoveDown],1
  263.      jae NoChange
  264.  
  265. StartNextKey:
  266.     mov [StuffMode-MoveDown], OFFSET NextKey - MoveDown
  267. NoChange:
  268.     ret
  269. CountDown endp
  270.  
  271. WaitEmpty proc near
  272.     mov ax,[BufferHead]
  273.     cmp ax,[BufferTail]
  274.      je StartNextKey
  275.  
  276.     ret
  277. WaitEmpty endp
  278.  
  279. StartPrompt:
  280.  
  281.     mov [StuffMode-MoveDown], offset ScanPrompt - MoveDown
  282.     mov [StuffPtr-MoveDown],si
  283.  
  284. ; si -> dx:BYTE, dy:BYTE, count:WORD, len:BYTE, attr:BYTE, st:BYTE * len
  285.  
  286. ScanPrompt:                             ; Find start posn'n
  287.  
  288.     mov si,[StuffPtr-MoveDown]
  289.  
  290.         lodsw                           ; AL = dx, AH = dy
  291.         mov cx,[Cursor]                 ; CL = X,  CH = y
  292.         sub cl,al
  293.          jae @@1
  294.         sub cl,cl
  295. @@1:
  296.         sub ch,ah
  297.          jae @@2
  298.         sub ch,ch
  299. @@2:
  300.         mov al,byte ptr [CrtWidth]
  301.         mul ch                          ; AX = Y-offset
  302.         sub ch,ch
  303.         add ax,cx
  304.         shl ax,1                        ; AX = Start of scan
  305.  
  306.          jmp short Scan1
  307.  
  308. StartFind:
  309.     mov [StuffMode-MoveDown], offset ScanText - MoveDown
  310.     mov [StuffPtr-MoveDown],si
  311.  
  312. ; si -> start:WORD, count:WORD, len:BYTE, attr:BYTE, st:BYTE * len
  313.  
  314. ScanText proc near
  315.  
  316.     mov si,[StuffPtr-MoveDown]
  317.         lodsw                           ; starting offset in screen
  318.  
  319. Scan1:
  320.         mov di,ax
  321.         lodsw
  322.         mov cx, ax                      ; # of char cells to search
  323.  
  324.     lodsw                ; AL = len, AH = attr
  325.     mov dl,al
  326.     xor dh,dh            ; Text len
  327.  
  328.         dec dx                          ; Skip first char in length
  329.  
  330.     mov bx, 0B000h
  331.     cmp [VideoMode],7
  332.      je @@1
  333.     cmp [VideoMode],3
  334.      ja @@done
  335.     mov bh,0B8h
  336. @@1:
  337.     mov es,bx            ; ES -> video segment
  338. ASSUME ES:NOTHING
  339.  
  340.         inc si                          ; Skip first char
  341.     cmp ah,255            ; ATTR = 255 -> no attr
  342.      je @@FindChar
  343.  
  344. @@FindCharAttr:
  345.         mov al,[si-1]                   ; First char to match
  346.         repne scasw
  347.          jne @@done
  348.         or dx,dx                        ; Remaining length = 0
  349.          jz @@found
  350.  
  351.         push cx
  352.         push si
  353.         push di
  354.         mov cx,dx
  355. @@l2:
  356.         lodsb
  357.         scasw
  358.          loope @@l2
  359.  
  360.         pop di
  361.         pop si
  362.         pop cx
  363.          jne @@FindCharAttr
  364.          je @@found
  365.  
  366. @@FindChar:
  367.         mov al,[si-1]
  368.         dec di
  369. @@l3:
  370.         inc di
  371.         scasb
  372.          loopne @@l3
  373.  
  374.          jne @@done
  375.  
  376.         or dx,dx
  377.          jz @@found
  378.  
  379.         push cx
  380.         push si
  381.         push di
  382.         mov cx,dx
  383. @@l4:
  384.         inc di
  385.         cmpsb
  386.          loope @@l4
  387.  
  388.         pop di
  389.         pop si
  390.         pop cx
  391.          jne @@l3
  392.  
  393. @@found:
  394.         add si,dx                       ; Point after text to search for
  395.     mov [StuffMode-MoveDown], offset NextKey - MoveDown
  396.         mov [StuffPtr-MoveDown],si
  397. @@done:
  398.         ret
  399. ScanText Endp
  400.  
  401.         ALIGN 2
  402.  
  403. BiosSeg         dw 40h
  404.  
  405. FirstByteToCopy label byte
  406.  
  407. StuffPtr    dw OFFSET StuffBuffer - MoveDown
  408. StuffEnd    dw ?
  409. StuffMode    dw OFFSET NextKey - MoveDown
  410.  
  411. CountLow    dw ?
  412. CountHigh    db ?            ; Use 24 bits for tick counter
  413.  
  414. active          db -1
  415.  
  416. ResidentEnd    EQU $
  417.  
  418. StuffBuffer    LABEL byte
  419.  
  420. StartMsg db 'StuffIt V',VerStr,' (C) Terje Mathisen 1989-90',13,10,'$'
  421.  
  422. SyntaxMsg label byte
  423.  
  424. db 'Syntax: Stuffit <commands>',13,10
  425. db '  Valid commands:',13,10
  426. db '  +|=[[hh:]mm:]ss     | Delay for(+) or until(=) a specified time.',13,10
  427. db '                         +45 will wait for 45 seconds.',13,10
  428. db '                         =14:00:00 will wait until 2pm.',13,10
  429. db '                         +0 will wait until the kbd buffer is empty.',13,10
  430. db '  <character code>    | Stuff a given character code.',13,10
  431. db '                         27 = <Esc>, 13 = <CR> etc.',13,10
  432. db '  @<scan code>        | Stuff a given scan code (char=0).',13,10
  433. db '                         @68 = F10, @73 = PgUp etc.',13,10
  434. db '  <char>:<scan>       | Specify both character and scan.',13,10
  435. db '                         43:74 = <Num+>',13,10
  436. db "  'TEXT'",' or "TEXT" | Stuff all the characters in TEXT',13,10
  437. db '  F<x>,<y>,<n>[,attr],"STRING" | Find "STRING" in an area starting at (X,Y),',13,10
  438. db "                         and beeing (N) char's long.",13,10
  439. db '                         Ignore text attributes, unless <attr> is specified.',13,10
  440. db '  P<dx>,<dy>,<n>[,attr],"STRING" | Find Prompt "STRING", starting at',13,10
  441. db "                         (CursorX-DX,CursorY-DY).",13,10
  442. db '  !                   | Reboot. (=0 ! will reboot at midnight.)',13,10
  443. db '  /F:FileName         | Read commands from <FileName>.',13,10
  444. db '  /B:nnnn             | Allocate room for <nnnn> bytes in TSR(512 default).',13,10
  445. db 'StuffIt /R will Remove (Unload) StuffIt from RAM.',13,10,'$'
  446.  
  447. UpdateMsg    db 'Resident copy updated!',13,10,'$'
  448.  
  449. StayResMsg    db 'Resident code loaded!',13,10,'$'
  450.  
  451. RemovedMsg    db 'Resident code removed from RAM!',13,10,'$'
  452.  
  453. WrongVerMsg db 'A different version of StuffIt is already resident!',13,10,'$'
  454.  
  455. NotRemovedMsg  label byte
  456.  db 'Resident code cannot be removed, as another '
  457.  db   'program is using the',13,10
  458.  db 'Timer (Int 8) and/or the Multiplex (Int 2F) '
  459.  db   'vector. Please remove all',13,10
  460.  db 'programs loaded after StuffIt, '
  461.  db   'and retry the operation.',13,10,'$'
  462.  
  463. RamErrMsg label byte
  464.  db 'Not enough RAM! (Need at least 128 kB to initialize program.)',13,10,'$'
  465.  
  466. FileErrMsg label byte
  467.  db 'Error reading input file!',13,10,'$'
  468.  
  469. ResidentToSmallMsg label byte
  470.  db 'Resident buffer to small! Try to remove it (/R) and reload.',13,10,'$'
  471.  
  472. ;FirstBlock      dw ?
  473. ;SecondBlock     dw ?
  474.  
  475.         JUMPS                           ; Allow inefficient code here!
  476.  
  477. Init proc near
  478. ASSUME DS:CODE, ES:CODE
  479.  
  480.         mov     ax,OFFSET StuffBuffer - MoveDown + 512 + 15
  481.         and     ax,0FFF0h
  482.         mov     [ResidentSize], ax
  483.  
  484. ; Start by relocating the program into a second segment
  485.  
  486. ;        mov     [FirstBlock],CS         ; Save segment addr
  487.  
  488.         mov     ah,4Ah
  489.         mov     bx,2000h                ; Realloc to 128 kB
  490. ;       mov     es,[FirstBlock]
  491.         int     21h
  492.         mov     dx, offset RamErrMsg
  493.          jc     ErrorMessage
  494.  
  495. ;        mov     ah,48h
  496. ;        mov     bx,1000h
  497. ;        int     21h                     ; Alloc second 64kB block
  498. ;        mov     dx, offset RamErrMsg
  499. ;         jc     ErrorMessage
  500.  
  501.         mov     ax,cs
  502.         add     ax,1000h                ; Point after 1st 64kB
  503.  
  504.         mov     es,ax
  505. ;        mov     [SecondBlock],es
  506.         sub     si,si
  507.         mov     di,si
  508.         mov     cx,(OFFSET ProgramEnd - OFFSET PspStart + 1) Shr 1
  509.         cld
  510.         rep     movsw
  511.  
  512.         push    es
  513.         mov     ax, OFFSET Continue
  514.         push    ax
  515.         retf
  516.  
  517. ;        pop     cs                      ; Jump into second copy of program!
  518. Continue:
  519.         push    ds
  520.         push    cs
  521.         pop     ds
  522.         pop     es                      ; DS=CS = SecondBlock, ES=FirstBlock
  523.  
  524. ; Move resident part of code as low as possible:
  525.  
  526.         mov     si, OFFSET HighStart
  527.         mov     di, OFFSET LowStart
  528.         mov     cx, OFFSET ResidentEnd - OFFSET HighStart
  529.         rep     movsb
  530.  
  531.     mov dx, OFFSET StartMsg
  532.     mov ah,9
  533.     int 21h
  534.  
  535.     call Parse
  536.  
  537.     cmp di, OFFSET StuffBuffer - MoveDown
  538.      je Syntax                  ; No parameter
  539.  
  540.         push    es
  541.         pop     ds                      ; DS,ES,SS = FirstBlock
  542.  
  543.     mov [StuffEnd-MoveDown],di
  544. ;    mov [StuffMode-MoveDown], OFFSET NextKey - MoveDown
  545. ;    mov [StuffPtr-MoveDown], OFFSET StuffBuffer - MoveDown
  546.  
  547. ;       mov [active-MoveDown],-1                 ; Initialize [active] flag
  548. ;       mov [BiosSeg-MoveDown],40h               ; Fast load of ES: when resident
  549.  
  550.     call TestSecond            ; Don't return if second copy!
  551.  
  552. ; Get old int 2F interrupt
  553.  
  554.     mov ax,352Fh
  555.     int 21h
  556.     mov WORD PTR [OldInt2F-MoveDown],BX
  557.     mov WORD PTR [OldInt2F+2-MoveDown],ES
  558.  
  559. ; Get old timer interrupt
  560.     mov ax,3508h
  561.     int 21h
  562.     mov WORD PTR [OldTimer-MoveDown],BX
  563.     mov Word Ptr [OldTimer+2-Movedown],ES
  564.  
  565. ; Enter our routine first
  566.  
  567.     mov ax,252Fh
  568.     mov dx, OFFSET Int2F - MoveDown
  569.     int 21h
  570.  
  571.     mov ax,2508h
  572.     mov dx, OFFSET MyTimer - MoveDown
  573.     int 21h
  574.  
  575.     mov ES, [DS:2Ch]
  576.     mov ah,49h
  577.     int 21h
  578.         mov word ptr [DS:2Ch],0         ; Signal no environment!
  579.  
  580.         push ds
  581.         push cs
  582.         pop ds
  583.     mov dx, OFFSET StayResMsg
  584.     mov ah,9
  585.     int 21h
  586.         pop ds
  587.  
  588.         mov cx,5
  589. @@CloseLoop:
  590.         mov bx,cx
  591.         dec bx
  592.         mov ah,3Eh
  593.         int 21h
  594.          loop @@CloseLoop
  595.  
  596.         push ss
  597.         pop ds
  598.     mov dx, [DS:ResidentSize]
  599.         cmp dx, [DS:Stuffend-MoveDown]
  600.          ja @@OK
  601.         mov dx, [DS:StuffEnd-MoveDown] ; DX = MAX(ResidentSize, StuffEnd)
  602.         mov [DS:ResidentSize],dx
  603. @@OK:
  604.         add dx,15
  605.         mov cl,4
  606.         shr dx,cl
  607.         mov ax,3100h
  608.     int 21h                         ; Go TSR with first block
  609.  
  610. Init Endp
  611.  
  612. FindFirst proc near
  613.  
  614.     mov dx,Semafor
  615.         mov ax,0E000h
  616.         xor bx,bx
  617.         int 2Fh
  618.  
  619.         cmp al,0FFh
  620.          jne @@done
  621.  
  622.     cmp bx, Version
  623.          je @@done
  624.  
  625.         mov dx, offset WrongVerMsg
  626.          jmp ErrorMessage
  627.  
  628. @@done:
  629.         ret                             ; Return ZERO if found
  630.  
  631. FindFirst endp
  632.  
  633. TestSecond proc near
  634.         call FindFirst
  635.          jne @@NotFound
  636.  
  637.         mov es,dx                       ; Save segment
  638.  
  639. ; This is the second copy! ES -> to first copy
  640. ; Test if enough room in resident program:
  641.  
  642.         mov ax,[StuffEnd-MoveDown]
  643.         cmp ax,[ES:ResidentSize]
  644.         mov dx, OFFSET ResidentToSmallMsg
  645.          ja ErrorMessage
  646.  
  647. ; Will now move all data into first copy, including pointers and StuffMode
  648.  
  649.     mov [ES:SelfModify-MoveDown], IRET_OPCODE ; Stop resident program
  650.     mov [DS:SelfModify-MoveDown], IRET_OPCODE ; Stop this version!
  651.  
  652.     mov si, offset FirstByteToCopy - MoveDown
  653.     mov di, si
  654.     mov cx, ax                      ; [StuffEnd]
  655.         sub cx,si
  656.     rep movsb
  657.  
  658.     mov [ES:SelfModify-MoveDown], PUSH_AX_OPCODE ; Restart resident version
  659.  
  660.     mov dx, OFFSET UpdateMsg
  661.     mov ah,9
  662.     int 21h
  663.  
  664.     mov ax,4C00h
  665.     int 21h
  666.  
  667. @@NotFound:
  668. ParseFinish:
  669.     ret
  670.  
  671. TestSecond ENDP
  672.  
  673. LocalSyntax:
  674.     jmp Syntax
  675.  
  676. EOF     EQU 26
  677.  
  678. Parse Proc near
  679.     cld
  680.     mov si, OFFSET CommandLine
  681.  
  682.         mov bl,[si-1]
  683.         sub bh,bh
  684.         mov byte ptr [si+bx],EOF
  685.  
  686. RestartParse:
  687.     mov di, OFFSET StuffBuffer - MoveDown
  688.  
  689. ParseNextChar:
  690.     lodsb
  691.     cmp al,EOF
  692.      je ParseFinish
  693.  
  694.     cmp al,' '
  695.      jbe ParseNextChar
  696.  
  697.     cmp al,'0'
  698.      jb @@NotDigit
  699.     cmp al,'9'
  700.      ja @@NotDigit
  701. @@Digit:
  702.     dec si
  703.     mov bx,255
  704.     call GetNumber
  705.     cmp al,':'
  706.     mov al,bl
  707.     mov ah,2
  708.      jne @@NotTwo
  709.  
  710.     push ax
  711.     mov bx,255
  712.     call GetNumber
  713.     cmp al,':'
  714.      je LocalSyntax
  715.  
  716.     pop ax
  717.     mov ah,bl
  718.  
  719. @@NotTwo:
  720.     Call SaveChar
  721.      jmp ParseNextChar
  722.  
  723. @@NotDigit:
  724.     cmp al,'/'
  725.      je ParseOption
  726.  
  727.     cmp al,'@'
  728.     jne @@NotFunc
  729.     mov bx,255
  730.     call GetNumber
  731.     mov ah,bl
  732.     xor al,al
  733.     stosw
  734.      jmp ParseNextChar
  735.  
  736. @@NotFunc:
  737.     cmp al,"'"
  738.      je @@Quote
  739.     cmp al,'"'
  740.      jne @@NotQuote
  741. @@Quote:
  742.     mov bl,al            ; Save starting quote char
  743. @@2:
  744.     lodsb
  745.     cmp al,13            ; Missing last quote
  746.      je Syntax
  747.     cmp al,bl            ; Ending quote?
  748.      je ParseNextChar        ; Yes, restart
  749.     mov ah,2            ; Assume scan = 2
  750.     call SaveChar
  751.      jmp @@2
  752.  
  753. @@NotQuote:
  754.     cmp al,'+'
  755.          jne @@3
  756.      jmp DeTime
  757. @@3:
  758.     cmp al,'='
  759.          jne @@4
  760.      jmp AtTime
  761.  
  762. @@4:
  763. ; Use ! to signal Reboot
  764.     cmp al,'!'
  765.      je SignalReboot
  766.  
  767.     cmp al,'f'
  768.      je FindNear
  769.     cmp al,'F'
  770.      je FindNear
  771.  
  772.     cmp al,'p'
  773.      je PromptNear
  774.     cmp al,'P'
  775.      je PromptNear
  776.  
  777. ; Fall into syntax error!
  778. Parse endp
  779.  
  780. Syntax Proc near
  781.     mov dx, OFFSET SyntaxMsg
  782.  
  783. ErrorMessage:
  784.         push cs
  785.         pop ds
  786.  
  787.     mov ah,9
  788.     int 21h
  789.     mov ax,4C01h
  790.     int 21h
  791. Syntax Endp
  792.  
  793. FindNear:
  794.         jmp FindText
  795.  
  796. PromptNear:
  797.         jmp PromptText
  798.  
  799. SignalReBoot:
  800.     mov ax,EXTENDED_CODE + (REBOOT_CODE * 256)
  801.     stosw
  802.      jmp ParseNextChar
  803.  
  804. ReadFile proc near
  805.  
  806.         cmp byte ptr [si],':'
  807.          jne @@Skip
  808.         inc si
  809. @@Skip:
  810.         mov dx,si
  811. @@Next:
  812.         lodsb
  813.         cmp al,' '
  814.          ja @@Next
  815.         dec si
  816.  
  817.         mov ax,3D00h                    ; Open file for Read_Only
  818.         mov byte ptr [si],al            ; Make ASCIIZ filename
  819.  
  820.         int 21h
  821.         mov dx, OFFSET FileErrMsg
  822.          jc ErrorMessage
  823.  
  824.         mov bx,ax
  825.         mov ah,3Fh                      ; Read File
  826.         mov dx, OFFSET ProgramEnd
  827.         mov si,dx
  828.         mov cx, - (OFFSET ProgramEnd)   ; Max Size in segment
  829.         int 21h
  830.         mov dx, OFFSET FileErrMsg
  831.          jc ErrorMessage
  832.  
  833.         add si, ax
  834.         mov byte ptr [si],EOF
  835.         sub si, ax                      ; Point back to start of filebuffer
  836.  
  837.         mov ah,3Eh
  838.         int 21h                         ; Close this file
  839.  
  840.          jmp RestartParse               ; Parse file buffer!
  841. ReadFile endp
  842.  
  843. SetBufferSize proc near
  844.  
  845.         cmp byte ptr [si],':'
  846.          jne @@Skip
  847.         inc si
  848. @@Skip:
  849.         mov bx,-( OFFSET StuffBuffer - MoveDown) + 32; Max text buffer
  850.         call GetNumber
  851.         add bx,OFFSET StuffBuffer - MoveDown + 15
  852.         and bx,0FFF0h
  853.         mov [ES:ResidentSize],bx
  854.          jmp ParseNextChar
  855.  
  856. SetBufferSize endp
  857.  
  858. ParseOption Proc near
  859.     lodsb
  860.         cmp al,'a'
  861.          jb @@Upper
  862.         cmp al,'z'
  863.          ja @@Upper
  864.         sub al,'a'-'A'
  865. @@Upper:
  866.         cmp al,'B'
  867.          je SetBufferSize
  868.         cmp al,'F'
  869.          je ReadFile
  870.     cmp al,'R'
  871.      jne Syntax
  872. @@Remove:
  873.     call FindFirst
  874.      jnz Syntax            ; First copy, nothing to remove!
  875.  
  876.     mov ax,3508h
  877.     int 21h
  878.     cmp bx, OFFSET MyTimer - MoveDown
  879.      jne @@CannotRemove
  880.     mov ax, es
  881.     cmp ax, dx
  882.      jne @@CannotRemove        ; Other TSR has timer vector!
  883.  
  884.     mov ax,352Fh
  885.     int 21h
  886.     cmp bx, OFFSET Int2F - MoveDown
  887.      jne @@CannotRemove
  888.     mov ax, es
  889.     cmp ax, dx
  890.      jne @@CannotRemove        ; Other TSR has Int 2F vector!
  891.  
  892. ; OK to remove previous copy from RAM
  893. ; First, restore timer vector
  894.  
  895.     push ds
  896.     mov dx,[word ptr ES:OldTimer-MoveDown]
  897.     mov ds,[word ptr ES:OldTimer+2-MoveDown]
  898.     mov ax,2508h
  899.     int 21h
  900.  
  901. ; Then, retore Int 2F vector
  902.  
  903.     mov dx,[word ptr ES:OldInt2F-MoveDown]
  904.     mov ds,[word ptr ES:OldInt2F+2-MoveDown]
  905.     mov ax,252Fh
  906.     int 21h
  907.  
  908.     pop ds
  909.  
  910. ; Next, release the memory segment
  911. ; ES -> to previos copy!
  912.  
  913.     mov ah,49h
  914.     int 21h
  915.  
  916.     mov dx, OFFSET RemovedMsg
  917.     mov ah,9
  918.     int 21h
  919.  
  920.     mov ax,4C00h
  921.     int 21h
  922.  
  923. @@CannotRemove:
  924.     mov dx, OFFSET NotRemovedMsg
  925.     mov ah,9
  926.     int 21h
  927.  
  928.     mov ax,4C01h
  929.     int 21h
  930.  
  931. ParseOption Endp
  932.  
  933. hour    dw ?
  934. min    dw ?
  935. sec    dw ?
  936.  
  937. DeTime Proc near
  938.     mov ax,EXTENDED_CODE + (DELTATIME_CODE * 256)
  939.      jmp short ParseTime
  940. AtTime:
  941.     mov ax,EXTENDED_CODE + (ATTIME_CODE * 256)
  942.  
  943. ParseTime:
  944.     stosw                ; Save marker for time
  945.  
  946. ; FIX BUG found by davidgb. HOUR and Min MUST be initialized to ZERO!
  947.  
  948.         xor ax,ax
  949.         mov [hour],ax
  950.         mov [min],ax
  951.  
  952. ; END OF bug-fix
  953.  
  954.     mov bx,59            ; Max value
  955.     call GetNumber
  956.     cmp al,':'
  957.      jne @@SaveSec
  958.  
  959.     mov [min],bx
  960.     mov bx,59
  961.     call GetNumber
  962.     cmp al,':'
  963.      jne @@SaveSec
  964.  
  965.     xchg bx,[min]
  966.     mov [hour],bx
  967.     mov bx,59
  968.     call GetNumber
  969.     cmp al,':'
  970.      je NearError
  971.  
  972. @@SaveSec:
  973.     mov [sec],bx
  974.  
  975. ; Now convert hour:min:sec into Timer ticks:
  976. ; Ticks= (hour*TicksPrHour) + (((min*60)+sec) * 34829 + 956) DIV 1913
  977.  
  978.     mov ax,(TicksPrHour - 65536)
  979.     mul [hour]
  980.     add dx,[hour]            ; DX:AX = hour*TicksPrHour
  981.     push ax                         ; Save DX:AX
  982.     push dx                         ; --- " ---
  983.  
  984.     mov al,60
  985.     mul [byte ptr min]
  986.     add ax,[sec]
  987.     mov dx,34829
  988.     mul dx
  989.     add ax,1913 Shr 1
  990.     adc dx,0
  991.     mov bx,ax
  992.     mov ax,dx
  993.     xor dx,dx
  994.     mov cx,1913
  995.     div cx
  996.     xchg ax,bx
  997.     div cx                ; BX:AX = Ticks in (min*60+sec)
  998.  
  999.     pop dx
  1000.     pop cx                ; DX:CX = Ticks in hours
  1001.  
  1002.     add ax,cx
  1003.     adc dx,bx            ; DX:AX = Total Ticks
  1004.  
  1005.     stosw                ; Save Low word of count
  1006.     mov al,dl
  1007.     stosb                ; Save high byte of count
  1008.  
  1009.      jmp ParseNextChar
  1010. DeTime Endp
  1011.  
  1012. PromptText:
  1013.         mov ax,EXTENDED_CODE + (PROMPT_CODE * 256)
  1014.         stosw
  1015.         mov bx,127
  1016.     call GetNumber
  1017.     cmp al,','
  1018.      jne NearError
  1019.     mov al,bl                       ; Save X value
  1020.         stosb
  1021.  
  1022.     mov bx,60                       ; 0<y<=60
  1023.     call GetNumber
  1024.     cmp al,','
  1025.      jne NearError
  1026.         mov al,bl
  1027.         stosb                           ; Save Y value
  1028.  
  1029.          jmp short Text1
  1030.  
  1031. NearError:
  1032.     jmp syntax
  1033.  
  1034. FindText proc near
  1035.     mov ax,EXTENDED_CODE + (FIND_CODE * 256) ; 255 + 3 -> flag for Find Text
  1036.     stosw
  1037.  
  1038.     mov bx,132            ; 0<x<=132
  1039.     call GetNumber
  1040.     cmp al,','
  1041.      jne GetError
  1042.         sub bl,1
  1043.          jb GetError
  1044.     mov cx,bx                       ; Save X value
  1045.  
  1046.     mov bx,60                       ; 0<y<=60
  1047.     call GetNumber
  1048.     cmp al,','
  1049.      jne GetError
  1050.         sub bl,1
  1051.          jb GetError
  1052.  
  1053.         mov al,80
  1054.         mul bl
  1055.     add ax, cx
  1056.         shl ax, 1
  1057.     stosw                ; Save X,Y as starting offset
  1058.  
  1059. Text1:
  1060.         mov bx,(132*60)                 ; Get length to search in
  1061.         call GetNumber
  1062.         cmp al,','
  1063.          jne NearError
  1064.         or bx,bx
  1065.          jz NearError                   ; Count must be > 0
  1066.  
  1067.         mov ax,bx
  1068.         stosw                           ; Save buffer length
  1069.  
  1070.     mov bx,255
  1071.     cmp byte ptr [si],'"'
  1072.      je @@SkipAttr
  1073.     cmp byte ptr [si],"'"
  1074.      je @@SkipAttr
  1075.  
  1076.     call GetNumber
  1077.     cmp al,','
  1078.      jne NearError
  1079.  
  1080. @@SkipAttr:
  1081.     mov ah,bl
  1082.     lodsb
  1083.     cmp al,'"'
  1084.      je @@1
  1085.     cmp al,"'"
  1086.      jne GetError
  1087. @@1:
  1088.     mov bx,di            ; Save current pos for len
  1089.     stosw                ; Store len + attr
  1090.  
  1091.     mov ah,al
  1092.     xor cx,cx
  1093. @@2:
  1094.     lodsb
  1095.     cmp al,EOF
  1096.      je GetError
  1097.     cmp al,13
  1098.      je GetError
  1099.     cmp al,ah
  1100.      je @@3
  1101.  
  1102.     inc cx                ; INC len
  1103.     stosb                ; Save Text
  1104.     jmp @@2
  1105.  
  1106. @@3:
  1107.     mov [ES:bx],cl            ; Save actual length!
  1108.  
  1109.     jmp ParseNextChar
  1110.  
  1111. FindText endp
  1112.  
  1113.  
  1114. GetError:
  1115.     jmp syntax
  1116.  
  1117. GetNumber proc near
  1118. ; input: SI -> first char to convert, BX = max value
  1119.     push cx                ; Use as temp buffer
  1120.     push dx                ; For mul
  1121.         push di                         ; For sign flag
  1122.  
  1123.     sub cx,cx
  1124.     mov ah,ch
  1125.         mov di,cx                       ; Zero DI -> Positive
  1126.  
  1127.         cmp byte ptr [si],'-'
  1128.          jne @@GetLoop
  1129.         dec di
  1130.         inc si
  1131.  
  1132. @@GetLoop:
  1133.     lodsb
  1134.     cmp al,' '
  1135.      jbe @@GetEnd
  1136.     cmp al,':'
  1137.      je @@GetEnd
  1138.     cmp al,','
  1139.      je @@GetEnd
  1140.  
  1141.     sub al,'0'
  1142.      jb GetError
  1143.     cmp al,9
  1144.      ja GetError
  1145.  
  1146. ; Valid decimal digit!
  1147.     xchg ax,cx
  1148.     mov dx,10
  1149.     mul dx
  1150.     add cx,ax
  1151.      jmp @@GetLoop
  1152. @@GetEnd:
  1153.     cmp al,EOF
  1154.      jne @@1
  1155.     dec si                ; Prepare to reload AL
  1156. @@1:
  1157.     cmp cx,bx            ; Valid value?
  1158.      ja GetError
  1159.     mov bx,cx
  1160.  
  1161.         or di,di
  1162.          jz @@done
  1163.  
  1164.         neg bx                          ; return -BX
  1165.  
  1166. @@done:
  1167.         pop di
  1168.     pop dx
  1169.     pop cx
  1170.  
  1171.     ret
  1172. GetNumber endp
  1173.  
  1174. SaveChar proc near
  1175. ; AL, AH = char, scan to save in StuffBuffer
  1176.  
  1177.     or al,al
  1178.      je @@Save2
  1179.     cmp al,224
  1180.      je @@Save2
  1181.  
  1182.     cmp al,254
  1183.      jae @@Save3
  1184.     cmp ah,2            ; Scan for normal chars
  1185.      jne @@Save3
  1186.  
  1187.     mov ah,14
  1188.     cmp al,8
  1189.      je @@Save3
  1190.     mov ah,15
  1191.     cmp al,9
  1192.      je @@Save3
  1193.     mov ah,28
  1194.     cmp al,13
  1195.      je @@Save3
  1196.     mov ah,1
  1197.     cmp al,27
  1198.      je @@Save3
  1199.  
  1200. ; Normal character, store just the char itself
  1201.  
  1202.     stosb
  1203.     ret
  1204.  
  1205. @@Save2:
  1206.     stosw
  1207.     ret
  1208.  
  1209. @@Save3:
  1210.     mov byte ptr [es:di],254
  1211.     inc di
  1212.     stosw
  1213.     ret
  1214. SaveChar endp
  1215.  
  1216. ProgramEnd label byte
  1217.  
  1218. CODE ENDS
  1219.     END start
  1220.  
  1221.  
  1222.