TITLE        FLOP        6-16-87        [6-16-87]
;
; Modified by Jacques Pierson, Nov 4, 1987. Make program general,
; i.e. use INT 1Eh to point to Disk Base Parameters. Also change
; the values used for FAST, and alter motor stepping time.
; Reset disk system when done, to ensure new parms in effect.
;
;  Author  Rick Housh
;
;For PC's and compatibles
;
;SPEED UP YOUR FLOPPIES  -  Start doing it now.
;
;For reference, see the column "C Notes", by Joseph Katz in SEXTANT
;magazine, May-June, 1987, pp. 46-53, and the article "Faster Disk
;Access for Heath/Zenith MS-DOS", by Pat Swayne, REMark magazine,
;August, 1986.  Both those articles deal with the concept of this
;simple utility.
;
;This program, while originally written for Heath/Zenith PC compatible
;computers, should work with any IBM PC compatible, with ANY version
;of MS-DOS, with assembly by ANY version of MASM.
;
;Reconfigures floppy drives to modify the head settle times and
;wait for motor start set in ROM.  These original times have proved
;to be overly conservative for the latest half-height drives with locking
;latches, in which the heads are always engaged.
;
;Based on an original idea by Pat Swayne, modified and translated by me
;into Turbo Pascal, rewritten by Joseph Katz in 'C', and here translated
;back into assembly language for MASM.
;
;All higher language overhead has been removed here, and the medium speed
;has been modified slightly, to allow some head settle time.  Experience
;and testing have indicated that, while reducing the head settle time to
;zero has increased transfer rates, it has also increased the number of
;retries caused by read or write errors.  If that does not prove to be
;a problem, use FLOP FAST, otherwise use FLOP MEDIUM.  Almost never should
;FLOP SLOW be required.
;
;How will you know if you have an excessive number of retries?  Beats me!
;My Shugarts do, my Teacs don't.
;
;This is NOT a TSR (memory resident) program.  It patches (on the fly)
;the memory locations in which DOS holds the DBP (disk base parameters).
;Therefore, it can be run at any time and will effectuate the changes
;immediately.
;
;Typically, switching from FLOP SLOW to FLOP FAST will result in an increase
;in the data transfer rate of about 30%, a worthwhile gain.
;
;Actually, to be completely "well-behaved" this program should get the
;segment and offset addresses of the disk parameters through function
;35 (hex) of DOS interrupt 21 (hex), which would supply the vector to
;them, then use function 25 (hex) to reset the vectors to entirely new
;locations.
;
;Nevertheless, in the interests of speed and size, direct memory
;access is used herein, based on the assumption that Bill Gates and
;"Big Blue" will not decide to grace us all with a change, and the
;values in the original locations are simply "patched" with new values.
;"And God bless us all," said Tiny Tim.
;
;In his column Dr. Katz expressed some anxiety that many Turbo Pascal
;programmers might be in better physical condition than he, implying
;some apprehension that he might be in danger of abuse for criticizing
;someone's choice of language.  I, for one, am just a simple country lawyer,
;as deskbound as any college professor such as Dr. Katz, and have no intention
;of disputing his claims that C can produce more compact programs.  On the
;contrary, I agree.  What I do not agree with is that one needs a C shell
;simply for the purpose of calling a few assembly language routines.
;
;To those of you who are interested, because I was taken somewhat to
;task by Dr. Katz for my Turbo Pascal program, which occupied about
;12,000 bytes, while his 'C' program only used about 6,000, this assembly
;program, which performs almost exactly the same function, uses only 472
;bytes, less than one standard MS-DOS disk sector.
;
;How can that be, you say?
;
;Well, it has nothing in it that it doesn't use, while compilers have
;a lot of unused baggage.  Yes, Turbo Pascal has more than C.
;
;You get what you pay for (with your coding time) and compilers carry
;overhead.  This is a very small program, and should be written in
;assembly language.  I have done it here just to show the contrast.
;
;It could even be written in <UGH> BASIC and compiled, in which case it
;would need about 32,000 bytes.  (Think of all the unused "PLAY" and
;"SCREEN" and "Who-Knows-What-Else" code which is carried along, unused).
;
;It is the "#include <stdio.h>" in Dr. Katz' C program which carries the
;C baggage.  The equivalent code is automatically included in Turbo Pascal
;and Basic.  Assembly includes nothing you don't write yourself.
;
;If you are interested, access Compuserve, Heath Users Group, (GO PCS 48)
;and download my Turbo Pascal program DSKSPD.ARC, in addition to this
;program, FLOP.ARC.  I could not find Dr. Katz' program SPIN.C (mentioned in
;his SEXTANT column) there.  I guess you'll have to buy that issue.
;
;The whole schmear (SP?) is a good lesson in why you should learn assembly
;language.
;
;                            Rick Housh
;                            Compuserve PIN 72466,212
;                            MUG (Mission, KS. User's Group)
;                            BBS (913) 362-9583
;
;  My thanks to Tom Gilbert, President, MUG, (Mission, Kansas Users' Group),
;  whose course in assembly language made this possible for me.
;
;       Next is assembly code for FLOP.COM
;
;First, the equates:
;
LF              equ     0Ah                     ;Line feed
CR              equ     0Dh                     ;Carriage return
BELL            equ     07h                     ;ASCII bell character ^G
CMD_LINE        equ     80h                     ;Command line length location
PARM_CHAR       equ     82h                     ;1st significant char in cmd ln
ALT_PARM_CHAR   equ     83h                     ;2nd    "         "    "  "   "

; offsets from Disk Base Parameters (pointed to by pseudo INT 1Eh) :
Step_Rate       equ     0       ;first nibble => (16-value)* 2 ms
                                ;Second nibble => head unload time
HEAD_SETTLE     equ     9
MOTOR_START     equ     10

SET_FLOPPIES        SEGMENT

      ASSUME DS:SET_FLOPPIES, SS:SET_FLOPPIES, CS:SET_FLOPPIES, ES:SET_FLOPPIES

        ORG        100h
START:        jmp        INIT_GETPARMS

NOPARM_MSG         db      BELL,CR,'FLOP.COM by Rick Housh'
                   db      ', Enhanced by JP, Nov 87'
                   db      CR,LF,'Optimizes floppy disk access times.'
                   db      CR,LF,'You must enter a valid parameter.'
                   db      CR,LF
                   db      'Proper syntax is FLOP/Speed or FLOP Speed'
                   db      ' where "Speed" is FAST,'
                   db      CR,LF,'MEDIUM, NORMAL, or SLOW,'
                   db      ' e.g., FLOP FAST, FLOP/FAST, FLOP F, or FLOP/F.'
                   db      CR,LF,'Normal and Medium are the same.'
                   db      ' Current settings not changed.'
                   db      CR,LF,'$'

;The next two db's are here only to allow you to get the above message printed
;to the screen when you enter TYPE FLOP.COM at the DOS prompt.
;FIXIT knocks out the $ sign and CTRL_Z makes the DOS TYPE command think it
;sees the end of a text file.  You may remove them and save three bytes if
;you don't care about that.

FIXIT              db      CR,' '
CTRL_Z             db      1Ah

;But don't remove the next four db's.  They are necessary messages.

FLOP_SET_MSG       db      CR,LF,'Floppies set to $'
FAST_MSG           db      'fast.',CR,LF,'$'
MEDIUM_MSG         db      'normal (medium).',CR,LF,'$'
SLOW_MSG           db      'slow.',CR,LF,'$'


INIT_GETPARMS:
;
;  We're going to fudge quite a bit here, in the interest of saving space.
;  We should throw away leading spaces and other junk, but won't.
;  We'll allow just one extra character at beginning of param line.
;  The worst that will happen is a "no parameter" message.
;
        mov     AH,[CS:CMD_LINE]                ;Get # of chars in param string
        cmp     AH,02h                          ;Are there less than two?
        jb      ERROR_EXIT                      ;Then not enough. Exit
        mov     AL,[CS:PARM_CHAR]               ;Get second char in param line
        cmp     AL,'/'                          ;Is it a slash?
        jnz     NOT_SLASH                       ;No? Then read it.
        mov     AL,[CS:ALT_PARM_CHAR]           ;Yes? Then read third.
NOT_SLASH:
        cmp     AL,'f'                          ;Is 1st char less than 'f'?
                                                ;e.g., upper case?
        jb      CONTINUE                        ;Yes? Then use it.
        sub     AL,20h                          ;Else make upper case.
CONTINUE:
        cmp     AL,'S'                          ;Is it 'Slow'
        jz      DO_SLOW                         ;Yes?  Then make floppies slow
        cmp     AL,'N'                          ;Is it 'Normal'?
        jz      DO_MEDIUM                        ;Yes? Then same as Medium
        cmp     AL,'M'                          ;Is it 'Medium'?
        jz      DO_MEDIUM                       ;Yes?  Then set floppies medium
        cmp     AL,'F'                          ;Is it  'Fast'? (Last option)
        jnz     ERROR_EXIT                      ;Yes?  Then just fall through
                                                ;else go to error exit.
DO_FAST:                                        ;If going to fast floppies
        mov     BH,00h                          ;Set head settle for 0 msec.
        mov     BL,00h                          ;and motor start wait for 0 ms
        mov     cl,0e0h                         ;4 ms step rate, no head unload
        mov     DX,OFFSET FAST_MSG              ;Get ready to print message
        jmp     SET_SPEED                       ;and do it.
DO_MEDIUM:                                      ;If going to medium
        mov     BH,01h                          ;Head settle at 1 msec.
        mov     BL,02h                          ;Mtr start wait at 250msec.
        mov     cl,0dfh                         ;6 ms step rate, head unload
        mov     DX,OFFSET MEDIUM_MSG            ;Get ready to print message
        jmp     SET_SPEED                       ;and do it.
DO_SLOW:
        mov     BH,0Dh                          ;Slow head settle is 13 msec!
        mov     BL,08h                          ;and mtr start wait is 1 sec!
        mov     cl,0fh                          ;32 ms step rate, head unload
        mov     DX,OFFSET SLOW_MSG              ;No other possibility here
                                                ;so just fall through.
SET_SPEED:
        push    DX                              ;Save floppy speed msg ptr
        mov     AH,09h                          ;Set for print string function
        mov     DX,OFFSET FLOP_SET_MSG          ;for "Floppies set to "
        int     21h                             ;and call DOS
        push    BP                              ;Save BP
        mov     BP,SP                           ;Move SP to BP
        push    ES                              ;Save Extra Segment
        xor     ax,ax                           ;Point to Int vectors
        mov     es,ax                           ;to ES
        mov     ax,bx                           ;save values in AX
        les     bx,dword ptr es:(1Eh*4)         ;get DBP address
        mov     byte ptr es:[bx + Step_Rate],cl
        mov     BYTE PTR ES:[bx + HEAD_SETTLE],ah ;Head settle time
        mov     BYTE PTR ES:[bx + MOTOR_START],al ;and Motor start time
        pop     ES                              ;Restore ES
        pop     BP                              ;and BP
        pop     DX                              ;Get speed message ptr
        mov     ah,0
        int     13h                             ;reset disk system
        jmp     FINIS
ERROR_EXIT:
        mov     DX,OFFSET NOPARM_MSG            ;Set ptr to info-error message
FINIS:
        mov     AH,09h                          ;and
        int     21h                             ;print the message at DX,
        mov     ax,4C00h                        ;terminate w/return code 0
        int     21h

        SET_FLOPPIES        ENDS
;
END        START
