home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 167 / TESRPARK.ZIP / TESRPARK.ASM
Assembly Source File  |  1988-07-25  |  24KB  |  508 lines

  1. PAGE 60,120
  2. TITLE TeSRpark.ASM -- TesSeRact park "hard" drive heads demonstration
  3. ;----------------------------------------------------------------------------
  4. SUBTTL  Originally TESSPARK.ASM & TSRPARK.ASM : TesSeRact Revision Level 1
  5. ;-----------------------------------------------------------------------------
  6. ;   TesSeRact(tm) -- A Library of Routines for Creating Ram-Resident (TSR)
  7. ;                    programs for the IBM PC and compatible Personal
  8. ;                    Computers.
  9. ;
  10. ;The software, documentation and source code are:
  11. ;
  12. ;       Copyright (C) 1986, 1987, 1988 Tesseract Development Team
  13. ;       All Rights Reserved
  14. ;
  15. ;       c/o Chip Rabinowitz
  16. ;       Innovative Data Concepts
  17. ;       2084 Woodlawn Avenue
  18. ;       Glenside, PA 19038
  19. ;       1-215-884-3373
  20. ;
  21. ;-----------------------------------------------------------------------------
  22. ;   This product supports the TesSeRact Standard for Ram-Resident Program
  23. ;   Communication.  For information about TesSeRact, contact the TesSeRact
  24. ;   Development Team at:
  25. ;       Compuserve:    70731,20
  26. ;       MCIMAIL:       315-5415
  27. ;   This MCIMAIL Account has been provided to the TesSeRact Development
  28. ;   Team by Borland International, Inc.  The TesSeRact Development Team
  29. ;   is in no way associated with Borland International, Inc.
  30. ;-----------------------------------------------------------------------------
  31. ;
  32. ; BASED on code originally provided by Jim Mischel
  33. ;
  34. ; ORIGINAL COPYRIGHT NOTICE:
  35. ;
  36. ;;;; AUTOPARK.ASM - program to automatically park the drive heads
  37. ;;;; at specified time intervals.
  38. ;;;;
  39. ;;;; Copyright (c) 1988, Jim Mischel
  40. ;;;;
  41. ;;;; This program has been assembled using MASM 5.0.  Changes may be required
  42. ;;;; for use with earlier versions.
  43. page
  44. ;;;;;                 TSRPARK.ASM -  Rick Housh
  45. ;;;;;
  46. ;;;;; TSRPARK.ASM - Modifications to TESSPARK.ASM to allow variable timing
  47. ;;;;; intervals from 1 to 9 minutes for autopark with use of numerical
  48. ;;;;; parameter on command line, to support manual parking with use
  49. ;;;;; of hotkey, with popup when on DOS command line, detection of
  50. ;;;;; park failure on installation, and communication with the resident
  51. ;;;;; program to allow dynamically changing the elapsed time between
  52. ;;;;; automatic parks.  Assembled using MASM 5.1.
  53. ;;;;;
  54. ;;;;; Everything is self-explanatory, except perhaps how to reset the
  55. ;;;;; timer when resident.  Just enter ' TSRPARK # ', where # is any number
  56. ;;;;; of minutes between 1 and 9, and the new value will be inserted in the
  57. ;;;;; resident portion of the program.  A message will confirm the change
  58. ;;;;; and even the MAPMEM display of residents will show the new value.
  59. ;;;;; Entering ' TSRPARK ' with no parameter will yield a confirming message
  60. ;;;;; if TSRPARK is resident, and an instructional message if it has not
  61. ;;;;; yet been installed.  When the hotkey is pressed from the DOS prompt
  62. ;;;;; a message is displayed, in addition to the TESSBEEP sound.  Inside
  63. ;;;;; a program, the sound will occur, but there will be no message.
  64. ;;;;;
  65. ;;;;; I have changed the "mysterious" headparking code somewhat, and tried
  66. ;;;;; to expand the comments to show how it really works.  It's not that
  67. ;;;;; complicated, and does NOT care whether the computer is an AT or not,
  68. ;;;;; contrary to the comments in the original TESSPARK.  I have also found
  69. ;;;;; an undocumented and useful function.  Tch, tch.  TSRCHECKRESIDENT
  70. ;;;;; returns the segment of the resident program in the es register if
  71. ;;;;; it has found the program installed in memory.  The documentation
  72. ;;;;; only mentions a result returned in the ax register.  I found this
  73. ;;;;; very useful, and have implemented it in TSRPARK.
  74. ;;;;;
  75. ;;;;; TSRPARK Modifications of TESSPARK, Rick Housh, CIS 72466,212 - 7/18/1988
  76. ;;;;;
  77. Comment~    Rick's method of communicating with the resident program is
  78.             efficient because the actions are performed by non-resident
  79.             code; but this version, TeSRpark by Tom Gilbert's Heart and
  80.             Mind, permits a command parameter "0" to effectively disable
  81.             TeSRpark by setting the delay to 60 minutes and demonstrates
  82.             communicating with the resident program through TSRUSERPROC:
  83.             Our objective has been to make the demonstration a thorough
  84.             one even though we realize that we can give advice; but not
  85.             the wisdom to profit by it: - Tom Gilbert's Heart & Mind.~
  86. ;;;;;
  87. ;;;;; To assemble this TesSeRact version:
  88. ;;;;;
  89. ;;;;;       MASM TESRPARK;
  90. ;;;;;       LINK TESS_ASM + TESS_BP + TESRPARK + TESS_END,TESRPARK;
  91. ;;;;;       EXE2BIN TESRPARK TSRPARK.COM
  92. ;;;;;       DEL TESRPARK.EXE and .OBJ
  93. ;;;;;
  94.  
  95. .model small
  96. .code
  97. page
  98. ;
  99. tinkle equ 1
  100. ;
  101. ;Sound TESSBEEP if set
  102. ;set tinkle to 0
  103. ;for no sound
  104. ;
  105. ; Ticks2wait is # of timer ticks to wait between the last drive access
  106. ; and parking the drive.  There are approximately 18.2 ticks per second.
  107. ;
  108. ; The maximum possible ticks2wait of 65536 ticks, very close to 1 hour,
  109. ; will be set for a command of "0".  For 1 - 9 ticks2wait 1092 to 9828.
  110. ;
  111. UserPtr     equ $
  112.                 db  "1234567890"        ;Possible minutes between parks
  113. ticks2wait      dw  ?                   ;Ticks to wait:
  114. ticks_min   equ 1092                    ;1092 = 1 minute
  115. tick_count      dw  ?                   ;Current count
  116. do_park         db  0                   ;Flag set to 1 when wish to park
  117. int13ptr        dw  0                   ;Saved location of INT 13 flag
  118.                                         ;  from TesSeRact data area
  119. ParkNum         dw  0                   ;TeSRpark's TesSeRact ID number
  120. ;
  121. ;I know the messages below look messy, but they stay resident and take
  122. ;up memory, so many of them do double duty.  Hence the many labels.
  123. ;                   Rick Housh
  124. ;
  125. are_parked label near
  126.                 db  7                   ;A bell to start already parked msg
  127. park_msg label near                     ;Message to display when popped up
  128.         db  13,10                       ; AND at DOS prompt
  129. ParkName        db  'TeSRpark'          ;TeSRpark's Identification string
  130.                 db  ' Status Report of Hard Drive'
  131. more_drives     db  '  '                      ;space if one, 's' if more
  132.                 db  13,10
  133.                 db  'Already parked. No action taken.'
  134.  
  135. are_parked_len equ  $ - are_parked                  ;message ends here
  136.                 db  13,'Drive'
  137. and_more_drives db  '  '
  138.                 db  'manually parked as requested. '
  139.  
  140. repark          db  13,10,'Will automatically repark drive'
  141. and_still_more  db  '  ',13,10
  142.  
  143. TSRminutes label near                    ;Minutes between parks in ASCII
  144.                 db  'xx minutes after next access.'
  145. carriage        db  13,10
  146.  
  147. repark_len  equ     $ - repark
  148. park_msg_len equ    repark - park_msg
  149.  
  150. public topstack
  151.                 db  48 dup('Back_Gnd')  ;BackProcStack - 384 bytes
  152.                 db  48 dup('TSR_Main')  ;MainProcStack - 384 bytes
  153. topstack equ this byte
  154. ;
  155. ; The parkit routine attempts to park all hard drives.
  156. ; Returns with carry set if park was unsuccessful.
  157. ;
  158. parkit  proc    near
  159.         mov     si,0080h                ;Hard drive ID's start at 80h
  160. pk0:    mov     ah,08h                  ;Function gets drive parms.
  161.         mov     dx,si                   ;DX is drive ID No.
  162.         int     13h                     ;Get drive parms-dl = # drives
  163.         jc      pkdone                  ;Error if carry, jump out
  164.         xor     dh,dh                   ;Don't need max head-side #
  165.         mov     di,dx                   ;Save drive count, dl to di
  166.         cmp     di,01h                  ;Is there at least one?
  167.         jb      pkdone                  ;If no hard drives, exit
  168.         jz      pk1                     ;Yes? Just set up for park
  169.         mov     more_drives,'s'         ;More than one?
  170.         mov     and_more_drives,'s'     ;Then put plurals
  171.         mov     and_still_more,'s'      ;in message strings
  172. pk1:    add     di,7fh                  ;Convert drive # to ID #
  173.         inc     ch                      ;CH is now tracks + 1
  174.         jnb     pk2                     ;Don't bump sectors
  175.         add     cl,40h                  ;CL is sectors
  176. pk2:    mov     ax,0c01h                ;Seek to cylinder
  177.         mov     dx,si                   ;DX is drive ID
  178.         int     13h                     ;Do the seek, park
  179.         inc     si                      ;Bump drive count
  180.         cmp     si,di                   ;Was it the last? No?
  181.         jbe     pk0                     ;Loop until all parked
  182. pkdone:
  183. if tinkle                               ;If you don't like it
  184. EXTRN TESSBEEP:NEAR                     ;set tinkle to 0
  185.                                         ;else sound TESSBEEP
  186.         call    TESSBEEP                ;whenever parking
  187. endif
  188.         ret
  189. parkit  endp
  190.  
  191. reset_it   proc near
  192.         mov     do_park,0               ;Say not to park
  193.         mov     bx,int13ptr             ;Get INT13 flag and
  194.         mov     byte ptr [bx],0         ;reset since parked.
  195.         mov     ax,ticks2wait           ;Use our timer to
  196.         mov     tick_count,ax           ;restart wait.
  197.         ret
  198. reset_it   endp
  199. ;
  200. ; TesSeRact Entry Points
  201. ;
  202. ;
  203. PUBLIC  TSRUSERPROC, TSRTIMERPROC, TSRBACKCHECK, TSRBACKPROC, TSRMAIN
  204. PUBLIC  TSRCLEANUP
  205.  
  206. TSRUSERPROC proc near                   ;Perform response to
  207.     assume  cs:_TEXT,ds:_TEXT,es:_TEXT  ;TesSeRact Function 20h
  208.         mov     si,offset TSRminutes    ;When it points the
  209.         xchg    si,di                   ;UserPtr {ES:DI} at new
  210.         lodsb                           ;ASCII minutes
  211.         cbw                             ;Extended to AX.
  212.         cmp     ax,"0"                  ;If NOT a "0"
  213.         jnz     twoASC                  ;Then make "0x"
  214.         mov     ah,6                    ;Else make "60"
  215. twoASC: or      ah,"0"
  216.         xchg    ah,al                   ;Reverse to Store in
  217.         stosw                           ;TSRminutes as ASCII
  218.         mov     al,ah                   ;Restore ASCII and
  219.         and     ax,0Fh                  ;Convert to value.
  220.         mov     cx,ticks_min            ;Calculate new
  221.         mul     cx                      ;Number of
  222.         mov     ticks2wait,ax           ;Ticks to Wait.
  223.         call    parkit                  ;Park the heads.
  224.         call    reset_it                ;Reset tick_count.
  225.         ret                             ;New delay is set.
  226. TSRUSERPROC endp
  227.  
  228. TSRTIMERPROC proc near
  229.         assume cs:_TEXT, ds:_TEXT
  230.         mov  bx,int13ptr                ;Check to see if
  231.         cmp  byte ptr [bx],1            ;drive has been accessed
  232.         jne  no_park                    ;since last parked and
  233.                                         ;exit if NOT...!
  234.         mov  do_park,0                  ;Else set park flag off
  235.         dec  tick_count                 ;If NOT the Last Tick
  236.         jnz  no_park                    ;Then exit
  237.         mov  do_park,1                  ;Else set park flag on
  238. clear_it:
  239.         mov  ax,ticks2wait              ;Use our own parameter
  240.         mov  tick_count,ax              ;to restart wait
  241.         mov  byte ptr [bx],0            ;and clear flag
  242. no_park:
  243.         ret
  244. TSRTIMERPROC endp
  245.  
  246. TSRBACKCHECK proc near
  247.         assume cs:_TEXT, ds:_TEXT
  248.  
  249.         mov     al,do_park              ;Return flag in AX.
  250.         xor     ah,ah                   ;If flag is non-zero
  251.         ret                             ;then TSRBACKPROC happens!
  252. TSRBACKCHECK endp
  253.  
  254. TSRBACKPROC proc near
  255.         assume cs:_TEXT, ds:_TEXT
  256.         call    parkit                  ;Attempt to park and
  257.         call    reset_it                ;reset ticks and fleas (flags).
  258.         ret
  259. TSRBACKPROC endp
  260.  
  261. Print_Msg   proc near
  262.         mov  ah,08h                     ;Read attribute at
  263.         int  10h                        ;current position then
  264.         or   ah,08h                     ;turn on intensity bit
  265.         mov  bl,ah                      ;and save it in bl
  266. putmsg: mov  al,0eh                     ;Using teletype mode
  267.         lodsb                           ;load ASCII character
  268.         cmp  al,20h                     ;Is it lower than space?
  269.         jb   no_att                     ;then don't paint attribute
  270.         push cx                         ;else save count
  271.         push ax                         ;Save character
  272.         mov  ax,0920h                   ;Paint with a space
  273.         mov  cx,1                       ;With this function
  274.         int  10h                        ;cursor doesn't move.
  275.         pop  ax                         ;Restore character
  276.         pop  cx                         ;and character count
  277. no_att: mov  ah,0eh                     ;Use teletype mode
  278.         int  10h                        ;to print characters
  279.         loop putmsg                     ;until end of string
  280.         ret
  281. Print_Msg   endp
  282.  
  283. TSRMAIN     proc near
  284.         assume cs:_TEXT, ds:_TEXT       ;On hotkey
  285.         mov  bx,int13ptr                ;check if accessed
  286.         cmp  byte ptr [bx],0            ;since last park
  287.         jnz  park_now                   ;If so, park em
  288.         mov  si, offset are_parked      ;else, display
  289.         mov  cx,are_parked_len          ;that already parked,
  290.         jmp  short display_parked_msg   ;skipping park routine
  291. park_now:
  292.         call parkit                     ;Park drive(s) and
  293.         call reset_it                   ;reset flags and ticks.
  294.         mov  si,offset park_msg         ;Point to park message
  295.         mov  cx,park_msg_len            ;and its length
  296. display_parked_msg:
  297.         push cx                         ;Save length of message
  298.         mov  ax,5453h                   ;TesSerAct function
  299.         mov  bx,16h                     ;to get InDos state
  300.         mov  cx,ParkNum                 ;This program's ID #
  301.         int  2fh                        ;Call function 16h
  302.         pop  cx                         ;{MUST pop message length}
  303.                                         ;{now in case of jump}
  304.         cmp  bx,1                       ;Check if at DOS prompt
  305.         jnz  mainX                      ;and end main if not
  306.         call print_msg                  ;else print it
  307.         mov  si,offset repark           ;Now print
  308.         mov  cx,repark_len              ;minutes to go
  309.         call print_msg                  ;between parks
  310.         mov  ax,5453h                   ;TesSeRact function to
  311.         mov  bx,21h                     ;stuff Keyboard Buffer
  312.         mov  cx,ParkNum                 ;from TeSRpark program
  313.         mov  di,offset carriage         ;There's an ASCII 13 here
  314.         mov  si,1                       ;Write one carriage
  315.         mov  dx,0101h                   ;return at medium
  316.         int  2fh                        ;speed as ASCII character.
  317. mainX:  ret                             ;DOS prompt should be back.
  318. TSRMAIN endp
  319.  
  320. TSRCLEANUP proc near
  321.         assume cs:_TEXT, ds:_TEXT
  322.         or   ax,ax
  323.         jnz  clean_term
  324. clean_init:
  325.         mov  cx,ParkNum                  ;Use program's ID num to
  326.         mov  bx,4h                       ;Get data area address.
  327.         mov  ax,5453h
  328.         int  2fh
  329.         add  bx,3h                       ;Adjust to "Was13" offset.
  330.         mov  int13ptr,bx                 ;Store address pointer.
  331. clean_term:
  332.         ret
  333. TSRCLEANUP endp
  334. ; End of resident program.  Initialization section follows:
  335. ;
  336. ; If TeSRpark already installed, change delay and/or display message.
  337. ; If not installed, attempt to park the drives and install the resident
  338. ; portion.
  339. ;
  340. EXTRN TSDOINIT:NEAR
  341. EXTRN TSCHECKRESIDENT:near
  342. EXTRN TSSETSTACK:near
  343. PUBLIC TESSINITSTART                     ;Required entry point
  344. TESSINITSTART:
  345.         assume cs:_TEXT, ds:_TEXT
  346. jmp start_init                           ;Jump over data
  347. ;
  348. ;Non-resident data area
  349. ;
  350. ;Following are the message strings for the transient part of the program
  351. ;They do not go resident and are not available to the TSR portion
  352. ;
  353. signon  label byte
  354.       db  13,10,'TESSPARK.COM Version 1.0, Copyright (c) '
  355.       db  '1988, TesSeRact(tm) Development Team',13,10
  356.       db  'All Rights Reserved',13,10,10
  357.       db  'Based on Original Code provided by Jim Mischel:',13,10
  358.       db  '   AUTOPARK 1.0  Copyright (c) 1988, Jim Mischel',13,10,10
  359.       db  "TeSRpark revision - Rick Housh with Tom Gilbert's Heart&Mind DPCS"
  360.       db  13,10
  361.       db  '   Hotkey instant park, variable auto park intervals,',13,10
  362.       db  '   popup message (at DOS prompt), detection of park',13,10
  363.       db  '   failure on installation, and change of timer while',13,10
  364.       db  '   resident without removal and reinstallation.'
  365.       db  13,10,10
  366.       db  7,'Command line error.  TeSRpark NOT loaded.',7,13,10,10
  367.       db  'Syntax: TESRPARK # (Where # is 1 - 9 [minutes] between parks)'
  368.       db  13,10,9,'or 0 to disable TeSRpark by delaying 1 hour.',13,10,'$'
  369. already_installed label byte
  370.       db  13,10,'TeSRpark already resident',13,10,7,'$'
  371. tsr_reset label byte
  372.       db  13,10,'Resident TeSRpark reset to',13,10,'$'
  373. installed label byte
  374.       db  13,10,'TeSRpark installed. '
  375. auto_time label byte
  376.       db  'Auto park every '
  377. minutes   label byte
  378.       db  '  '
  379.       db  ' minutes.',13,10
  380. HotKeyM   label byte
  381.       db  'Left Shift + Alt + "P" parks hard drive(s) instantly!',13,10,'$'
  382. ding_a_ling label byte
  383.       db  'A "tinkle" will sound when heads are parked.',13,10,'$'
  384. bad_park label byte                     ;BAD PROBLEM, LOTS OF BELLS
  385.       db  13,10,7,'Hard drive error.  Unable to park hard drive(s).'
  386.       db  13,10,7,'Terminating.',13,10,7,'$'
  387.  
  388. get_cmd_line:
  389.         mov  si,80h                     ;Start of command line
  390.         mov  bx,9                       ;Index to numerals
  391.         lodsb                           ;Command length
  392.         cmp  al,0                       ;If no command
  393.         jz   cmd_err                    ;or if command
  394. get_1:  lodsb                           ;ends before a
  395.         cmp  al,13                      ;numeric input
  396.         jz   cmd_err                    ;then CY exit.
  397.         mov  di,offset UserPtr          ;else scan the
  398.         mov  cx,10                      ;ten numerals.
  399.         repne scasb                     ;If no match
  400.         jne  get_1                      ;then loop
  401.         sub  bx,cx                      ;else use index to
  402.         mov  di,offset UserPtr          ;return DI pointer
  403.         add  di,bx                      ;for TSRUSERPROC,
  404.         cbw                             ;AX character and
  405.         ret                             ;carry flag clear.
  406. cmd_err:
  407.         stc                             ;Set carry flag
  408.         ret                             ;and return
  409. ;
  410. ;  Although I can't find it in the version 1.00 TesSerAct documentation,
  411. ;  TSRCHECKRESIDENT, if it finds the code resident, returns not only
  412. ;  0ffffh in ax but the segment of the resident version in the es register.
  413. ;  This makes it unnecessary to call multiplex function 4 to find
  414. ;  its location.  I will use that undocumented feature here, but
  415. ;  we should have been told. - Rick Housh
  416. ;
  417. start_init:
  418.         mov  si,offset ParkName         ;Check to see if resident
  419.         mov  di,offset ParkNum          ;Returns segment of resident
  420.         call TSCHECKRESIDENT            ;program in es if installed
  421.         or   ax,ax                      ;If NOT already installed
  422.         jz   do_install                 ;then attempt to install
  423.         call get_cmd_line               ;else if command invalid
  424.         jc   just_checking              ;just display status and exit
  425.         cmp  ax,"0"                     ;If NOT a "0"
  426.         jnz  ASCtwo                     ;then make "0x"
  427.         mov  ah,6                       ;else make "60"
  428. ASCtwo: or   ah,"0"                     ;in resident data areas.
  429.         mov  minutes,ah                 ;Store Most Significant and
  430.         mov  minutes[1],al              ;Least Significant Bytes in
  431.         mov  es:[82h],ah                ;message and TSR command line
  432.         mov  es:[83h],al                ;but NOT TSRminutes or ticks.
  433.         mov  ax,5453h                   ;Use TesSeRact Call User
  434.         mov  bx,20h                     ;Function with ES:DI to
  435.         mov  cx,es:ParkNum              ;send the new TSRminutes.
  436.         int  2Fh                        ;Silly, but demonstrates.
  437.         mov  dx,offset tsr_reset        ;Tell em have changed it
  438.         mov  ah,09h
  439.         int  21h
  440.         jmp  short display_time         ;and display new value
  441. just_checking:
  442.         mov  dx,offset already_installed
  443.         mov  ah,09h                     ;Display "already resident"
  444.         int  21h
  445.         mov  ax,word ptr es:[TSRminutes]
  446.         mov  word ptr minutes,ax        ;Move resident value here and
  447. display_time:
  448.         mov  ah,09h
  449.         mov  dx,offset auto_time        ;Display current minute value
  450.         int  21h
  451. term_it:
  452.         mov  ax,4c01h                   ;Set error code to 1
  453.         int  21h                        ;and quit
  454. do_install:
  455.         mov  si,offset topstack         ;Divide stack into
  456.         mov  di,si                      ;PopUpStack and
  457.         sub  si,384                     ;BackGroundStack
  458.         call TSSETSTACK                 ;Two 384 byte stacks
  459.  
  460.         call get_cmd_line               ;If invalid command line
  461.         jc   cmdline_err                ;then display message and exit
  462.         cmp  ax,"0"                     ;else if NOT a "0"
  463.         jnz  ASC_2                      ;then make "0x"
  464.         mov  ah,6                       ;else make "60"
  465. ASC_2:  or   ah,"0"                     ;in local data areas.
  466.         xchg ah,al                      ;Account for Lo/Hi
  467.         mov  word ptr minutes,ax        ;Store Message and
  468.         mov  word ptr TSRminutes,ax     ;TSR minutes ASCII.
  469.         mov  al,ah                      ;Restore minutes to AL and
  470.         and  ax,0Fh                     ;Convert ASCII to numeric.
  471.         mov  cx, ticks_min              ;NOTE: 0 counts 65536 ticks.
  472.         mul  cx                         ;Multiply by ticks
  473.         mov  di,offset ticks2wait       ;per minute (1092).
  474.         stosw                           ;Initialize wait and
  475.         stosw                           ;current timer counts.
  476.         call parkit                     ;If heads park Ok
  477.         jnc  good_park                  ;then set command and report
  478.         mov  dx,offset bad_park         ;else print an error report.
  479.         mov  ah,09
  480.         int  21h
  481.         jmp  term_it                    ;and quit with error code
  482. good_park:
  483.         mov  cx,offset HotKeyM          ;Calculate length of
  484.         mov  si,offset minutes          ;minutes message to
  485.         sub  cx,si                      ;carriage return.
  486.         dec  cx
  487.         mov  di,82h                     ;Transfer new
  488.         mov  [di-2],cl                  ;length and
  489.         rep  movsb                      ;new command.
  490.         mov  dx,offset installed
  491.         mov  ah,09                      ;Show that it's installed
  492.         int  21h
  493.         mov  dx,offset ding_a_ling
  494.         mov  ah,09                      ;and that it tinkles.
  495.         int  21h
  496.         mov  dx,offset TESSINITSTART    ;Set last resident byte
  497.         mov  bx,1170h                   ;No pop graphics.  Background,
  498.                                         ;main, user and main procedures
  499.         mov  ax,0a19h                   ;Left Shift + Alt + "P" will be
  500.         jmp  TSDOINIT                   ;hotkey for manual park.
  501. cmdline_err:
  502.         mov  dx,offset signon
  503.         mov  ah,09
  504.         int  21h                        ;Display the signon message
  505.         jmp  term_it                    ;and quit with error code
  506. _TEXT ends
  507.         END
  508.