FASTBUFF v2.0 Do-It-All Keyboard Enhancer David Steiner November 1987 The only thing you really need to know in order to use FASTBUFF is that to install it you type FASTBUFF and hit the ENTER key. To see the results just hold down a key and watch how fast it goes. If you run into problems with a program that doesn't like FASTBUFF then you may want to look over this documentation a little closer. Even if you're not entirely sure you like the idea of such a keyboard enhancement program, at least give FASTBUFF a trial run. After all, its a free program. You will quite likely find it frustrating to go back to the normal repeat rate and buffer size. Version 2.0 is a fairly large improvement over version 1.0, even though this one has been released fairly quickly after the first. The only bug fix was related to typing in characters via the numeric keypad. It seems that the repeat function always ended up set, and wouldn't stop till you hit another key. REQUIREMENTS FASTBUFF was written on an IBM XT compatible computer. It should work with true IBM PC's just fine. I've also tested it on AT compatibles, and it seems to work fine. The video blanking works fine for CGA and monochrome systems, but not EGA. I doubt it will work for other video cards either. I'll try to provide support for them at a later date when I have time. If you don't have a video card that is supported, it is best to disable this function. As far as memory is concerned, FASTBUFF only eats up 1500 bytes when its using a 100 character buffer. Even if you set the buffer as large as it will go (269 characters) FASTBUFF still only take up about 1800 bytes. As usual, there are some restrictions on what order you load FASTBUFF. Although it is a well-behaved resident program you still get the best results if you load it early. This has to do with who "hooks" which vectors and will be discussed below in more detail. Some programs, however, are very low-level and should be loaded before FASTBUFF. Such programs include the keyboard drivers supplied with MS-DOS (KEYxx.COM). FEATURES Variable Size Keyboard Buffer: FASTBUFF takes control of the keystroke interrupt in order to allow you to set the size of buffer you like. The default is 100 characters, but may range from 25 to 269 characters. Increased Key Repeat Rate: By using the timer interrupt we are able to modify how fast keys are repeated. When FASTBUFF is activated you may select between a repeat rate of 18 or 36 characters per second. Unlike most key quickeners that I've seen, FASTBUFF has a fairly smooth repeat rate even in its fast mode. Note that you may also select the normal repeat rate by turning FASTBUFF off. Anti-skid Braking: Given a large buffer and fast repeat rate you could get way ahead of your application when holding a key down. FASTBUFF uses a simple but effective method of preventing this: it doesn't put repeated characters into the buffer until the application program is ready (i.e. the buffer is empty). Screen Blanking: If you leave your computer unattended for over fifteen minutes FASTBUFF will automatically blank the video screen in order to avoid "burning" characters into the display screen. The screen may be restored by pressing any key. Repeat Characters Entered Through the Alt-Keypad: The IBM will allow you to enter characters by holding the ALT key down and typing the ASCII character number on the numeric keypad. When you release the ALT key the character is inserted at the cursor position. FASTBUFF also provides a method of repeating the key entered this way. Enter Graphics Characters With the Alt-Keypad: Some of us poor folks with IBM compatibles have a BIOS that gets confused when entering graphics characters via the keypad (character numbers over 127). FASTBUFF takes control of this function and returns these characters correctly. This fix also pertains to compatibles that do not return the normal scan code (0) for these characters. Disable FASTBUFF: It is possible that you may need to use a program that doesn't seem to like FASTBUFF. To account for this possibility you may turn off the FASTBUFF functions in order to use these programs. After leaving the conflicting application, you may re-enable FASTBUFF again. RUN-TIME CONTROL KEYS While FASTBUFF is resident you have several options for the way it controls your keyboard. First we'll cover the option for clearing the FASTBUFF keyboard buffer: ALT-RIGHT SHIFT: Clear the keyboard buffer You may clear the typeahead buffer by pressing the ALT and RIGHT SHIFT keys simultaneously. This clears anything in the buffer, even if you've already hit the ENTER key. This function is not active when FASTBUFF is turned off. The rest of the keys are entered by pressing keys while holding down the FASTBUFF command key. This key has been chosen to be the "5" key located on your numeric keypad, in an effort to clash with as few other resident programs as possible. I will denote this key as [5] from here on out. You must also note that this key is distinct from the "5" key located in the top row of the keyboard. [5]-MINUS: Set repeat rate slow By pressing the [5] and the "-" key located right next to it you may set FASTBUFF to use its slower repeat rate (18 characters per second). Note that this is still somewhat faster than the normal repeat rate. Most of the time this mode will also produce a "smoother" repeat. [5]-PLUS: Set repeat rate fast The default setting for FASTBUFF is the fast repeat rate (36 characters per second). However, this is too fast for some applications, so you may switch between the fast and slow modes to suit your needs. [5]-DEL: Turn off FASTBUFF This version of FASTBUFF has been rewritten to conflict with as few other programs as possible. You shouldn't find too many programs that will require you to turn FASTBUFF off. On the other hand, you may occasionally wish to reduce the keyboard buffer and repeat rates to the normal values and this switch allows you to do just that. [5]-INS: Turn FASTBUFF back on If you've turned off FASTBUFF, you can re-enable it by pressing these keys simultaneously. COMMAND LINE SETUP PARAMETERS I've tried to set the defaults for FASTBUFF the way most people will like them. However, if there is something you would like different there are a few startup values you may change. To do this you may enter setup codes on the command line after the file name. For example: FASTBUFF /b255/v0/d9/s would set the buffer to 255 characters, the video blanking off, the character repeat delay to about a half second and the repeat rate to 18 characters per second (FASTBUFF's slow repeat). Each parameter consists of a slash "/", the parameter letter and finally a number, if one is required. These may be entered in any order, and even repeated. When a parameter is repeated the rightmost one takes precedence. FASTBUFF will not be installed if an invalid parameter is entered, instead you will get a help screen. You may get this help screen at any time by typing: FASTBUFF ? The help screen provides information on both the command line parameters and the run-time command keys. PARAMETER DESCRIPTIONS /Bn : Set buffer size If you can actually type fast enough to fill the default buffer you may wish to select a larger one by using this parameter. Valid sizes are from 25 to 269. Note that FASTBUFF will accept numbers larger than 269, but the value actually used will be seemingly random. /Vn : Set screen blanking delay The amount of time FASTBUFF will wait for some form of input or screen I/O before blanking the screen may be set with this parameter. Valid numbers range from 0 to 60 minutes. Again, larger numbers may be entered, but will produce delay times ranging from 1 to 60 minutes anyway. Setting the blanking delay to zero will disable it. The video blanking has been tested with CGA, monochrome (Hercules also) and EGA cards. It works fine with all except the EGA. If you have this type of video card, or others not listed, it is suggested that you disable screen blanking just to be safe. When I get some time and some more references I'll put together another version that supports other cards. /Dn : Set repeat delay This parameter sets the amount of time (in timer clicks) a key must be held before it is repeated. The default setting is 5 clicks, which translates to about a quarter of a second. I believe the BIOS repeat delay is somewhere around 9 (a half second) and you may prefer that delay. /F : Select fast repeat rate Actually, there isn't really any reason for this option since the default setting is fast. I included it mostly for consistency. The fast repeat rate is 36 characters per second. /S : Select slow repeat rate This parameter sets the repeat rate to FASTBUFF's slower rate, 18 characters per second. The BIOS repeat rate seems to be about 9 char/second, so FASTBUFF is still quick, even in its slow mode. Note that setting the fast or slow repeat rate only affects the startup mode, the repeat rate may still be switched at any time by using the run-time commands listed above. SPECIFICS Now we will start getting a little more specific about what each of these functions do. This may (or may not) be helpful for those of you mucking about in the source code. HOOKS If you've had your computer for long, you've probably already heard too much about hooking vectors and related quirks of the IBM. Sorry, but FASTBUFF is something of a "system" program rather than an "application" and hooking is a requirement (wipe that smirk off your face). In order to get all of the FASTBUFF features we only had to hook into three interrupt vectors, although we considered a few others. Here is a list of the vectors and why we use (or didn't use) them: 09H : Keystroke We had to take over this vector in order to steal characters from the BIOS input buffer and put them into ours as they were typed. Well, as long as we've taken over the keystroke interrupt why not make our control key something that isn't likely to conflict with other programs (like the five on the numeric keypad). Hey, we can fix that silly bug with our BIOS that won't let us enter graphics characters on the keypad too. (16H : Keyboard I/O) Well, now we need to be able to get those characters back out of our new buffer, since we've stolen them from the BIOS. We could take over this interrupt and return characters from our buffer whenever the system asks for keyboard input, but it turns out that this isn't a good idea. The problem is that there are just too many programs that access the BIOS keyboard buffer directly, without consulting the system. Another, less obvious problem, is that if we completely take over parts of this interrupt, we don't pass control on to the next program that hooked this vector. This is becomes a problem when such programs are loaded before FASTBUFF. If you've already seen FASTBUFF v1.0 you know that this was the original design. Version 2.0 uses the method described under interrupts 08 and 1C, and is much less likely to cause problems with other programs. (08H : Hardware Timer Interrupt) Lets see... If we don't use interrupt 16 to return characters, what are we going to do? Well lets try checking once in a while to see if the normal BIOS buffer is full and if not insert characters from our buffer into the BIOS buffer. The only reliable way to do this is to hook into the timer click interrupt. This allows us to perform this check 18.2 times per second (how often this interrupt is generated by the system). Well, we have the right notion, but we really shouldn't use the hardware interrupt for this. The problem is that the system performs important actions every time this interrupt is issued, and if we take control first we will slow down its response. The "proper" method uses the next interrupt. 1CH : Get Control on Timer Tick This interrupt was provided by the system to allow actions of just the type we want. If we're careful we can insert our code and pass control on to other programs that hook this vector with no problems. Now, we already know that we are going to be using this interrupt to update the BIOS buffer, so as long as we're here let's add another function that has a reasonable low overhead. Lets set up a counter to keep track of how long its been since the last screen I/O operation was performed. If the computer sits unattended for too long we can then blank the screen to avoid damaging the monitor. To do this right we'll have to reset the counter every time a key is pressed or something is written to the screen, which means we'll have to hook one more vector. 10H : Video I/O To reset our screen blanking cursor when a key is pressed is no problem, we can just insert a few lines of code in our interrupt 9 handler. However to detect if something is written to the screen we must take over this interrupt. When a program is accessing the video in the "proper" way it will use this function interrupt to make changes to the screen. Therefore we should reset our screen blanking counter whenever this interrupt is used. Again, there are some problems. For example, many programs write to the screen directly and never bother the system with an interrupt 10 call. For the video blanking this really isn't very serious since the worst that could happen is that the screen gets blanked when there really is some activity. All the user will have to do is type any key and the screen will be restored by our interrupt 9 reset function. Finally, we decide to add one more frill. We'll give FASTBUFF some way to indicate that it is present if someone asks nicely. This will enable us to detect if FASTBUFF is present when the program is executed and abort the installation in order to avoid having two copies in memory. We will add this feature as part of our interrupt 10 handler for two reasons. The reason for choosing an interrupt to perform this function is that we don't know where in memory a previous copy of FASTBUFF might be located, so we need this alternate method for detecting it. We choose interrupt 10 to perform this function since it is the only one we have hooked that normally accepts input parameters and returns output. Note that in the above list the interrupt vectors listed in parenthesis are not actually used by FASTBUFF, they are listed only as alternative considerations. Well that list should give you a feel for how FASTBUFF works. Of course, I didn't actually design it in that manner, I used a much more professional approach (I wrote version 1.0 and started discovering bugs a couple of days later). THE SOURCE CODE In this section I'll go over what each interrupt handler in the source code does, in a general manner. I won't cover the initialization code, other than detecting if FASTBUFF is installed, since that stuff is small potatoes. If you don't fully understand interrupt vectors yet, there isn't much I can help you with here. There are entire books written on the subject. INT 9 - KEYSTROKE The first thing I should note here is how and when this interrupt is called. This interrupt is issued every time a key is pressed or released. The keyboard returns the scan code (a byte) through one of the input ports to let the computer know which key it was. The scan codes that have meaning to us are defined in the equates set in the first section of the source code. These codes are for the "make" signals, or when the key is depressed. The "break" code, or when the key is released, can be calculated by setting the high bit of the make code (code+80H). Another note is that FASTBUFF keeps all of its status information in a single byte. We use the bits in this byte (switches) to indicate certain conditions in FASTBUFF. The bits will be accessed by anding and oring the status byte with masks that we set in the equates section of the code. Setup: When we enter this interrupt there are a few things we must do along the lines of resetting FASTBUFF. The first such item is turning off our repeat switch bit (repmask). This is done so FASTBUFF won't continue to repeat a character after another key is pressed. Next we set the ES register so we can use it to access the BIOS data used by the rest of the system. After doing this we reset the BIOS break detection bit. We do this so we can test it again after the old interrupt 9 call in order to see if we need to clear our buffers. Video counter: The next item we should take care of is resetting our video blanking counter. If this interrupt is called the user must have typed some key, so we should start the blanking countdown again. A related check is to see if the video is currently shut off. If the user was gone for a while and the screen was shut off we now need to turn it back on since they are obviously back. Command Key Check: Next we need to see if the command key is currently pressed. We keep track of this by setting a bit (ctrlmodemask) in our FASTBUFF status byte when the [5] key is pressed. We leave this bit set until we receive the scan code indicating that the [5] key was released. If the command mode bit is set we then need to see if second key in a control key combination was pressed. If one of the two combinations were pressed for turning FASTBUFF on or off then we need to set the appropriate bit in our status byte (fbmask). If FASTBUFF is turned on or off we need to clear our keyboard buffer just to be certain there aren't any problems caused by the switch. Note that even when we intercept these command keys that we still pass control on to the old interrupt handler, even though we ignore any characters it may have tried to put in the BIOS buffer. This pass is done to minimize the possibility of FASTBUFF clobbering another resident program. Next, if FASTBUFF is on, we need to check for the key combinations that are used to set the key repeat speed. We don't perform this check when FASTBUFF is off, again to minimize clashing with other resident utilities. FASTBUFF on/off: At this point we have taken care of all the required resettings and checks so we may finally check if FASTBUFF is active. If FASTBUFF is currently turned off we may safely make the call to the old interrupt 9 handler and exit the interrupt call. First Alt-Key Break Check: One of the things FASTBUFF is supposed to do is take care of the Alt-keypad entries and make sure they are returned in the standard IBM BIOS format. The first step in this direction is to watch for the scan code that indicates that the ALT key was released. If this code is detected we will steal a copy of the character number created by the BIOS. This character is stored in a byte in the BIOS data area (BIOSaltbuff). We need to store it now since it will be zeroed when the call to the old interrupt 9 handler. Check for Clear Key Combination: Another control-type key we need to check for is the CTRL-RIGHT SHIFT clear buffer combination. If this key is detected (while FASTBUFF is active) we need to clear out the buffer. Call Old Interrupt Handler: If we make it this far without encountering a control key we finally call the old keystroke interrupt handler. We are doing this for two reasons: its a good idea to pass control on to the old one and there is no reason to duplicate the BIOS code that translates the keyboard scan codes into ASCII characters. Something that I'll cover in more detail later is the reason for setting a bit in our status byte that indicates we are calling the old interrupt 9 handler. After calling the old BIOS handler we can tell if a character was entered by whether or not the BIOS tail pointer has moved. After storing this character and checking for a new character we restore the old value of the BIOS tail pointer. This effectively removes the character from the BIOS buffer. CTRL-BREAK Check: We now need to check the CTRL-BREAK bit again to see if that key combination was pressed. If so we have to clear the buffers and output a dummy character. The dummy character is done to emulate the way the normal BIOS returns a CTRL-BREAK sequence. New Character Detected: If a new character was input we need to remove it from the BIOS keyboard buffer and insert into ours. Before we insert the character we want to check again to see if it was entered via the keypad. If so we must first fix the character code to be inserted. The fix for these characters simply consists of retrieving the character we saved earlier and forcing it into the standard format. The standard format is just the ASCII code in the low byte and a zero in the high byte. If your system already does this correctly, then the fix doesn't hurt anything anyway. The actual insertion of the character into our buffer will be covered in the next section. PUT CHARACTER INTO OUR BUFFER Last Character: This check is done to make sure that the character just just entered did not come from the standard BIOS repeat function. If the character input matches the last one typed it may be assumed that the scan code came from the standard repeat and we will ignore it. The character is ignored in order to avoid a repeat speed that looks jerky. Note that we may assume that a character that matches the lastchar value is from the standard repeat since we would see the break scan code if the key was released. Repeat Delay: There are two variables that must be set for use later by the repeat function. The first is the one mentioned above. We need to keep track of the last character entered for use by the repeat function. Since this is a new character we set the counter for the repeat delay to its starting value. Increment Tail Pointer: The next step is to increment the tail pointer on our buffer. If this incremented value matches the head pointer then the buffer is full and we need to beep to tell the user. Turn the repeat function on: Since we detected a new typeable character we need to turn the repeat function back on. This tells the interrupt 1C handler to repeat the character when it is called later. There is another modification that FASTBUFF makes to the character repeat function. If the character was entered through the keypad its scan code will be zero. If this is true and the user is currently holding down the LEFT SHIFT key we will allow the character to repeat until the LEFT SHIFT is released. INT 10 - VIDEO I/O Reset Blanking Counter: The first thing to do is reset the screen blanking cursor. If the program performs any video output then we assume that the counter should be reset. Check if Video Disabled: After resetting the counter we still need to make sure the video is still on. If it was disabled earlier the video active bit will have been cleared to let us know that we need to restore it. Function FAH: A final addition to this interrupt will be a way for FASTBUFF to indicate that it is resident. This will allow us to avoid loading two copies of FASTBUFF. All we need to do to implement this is to check if the AH register contains FAH. If it does we will return 00FAH in the entire AX register to let the calling program know we're resident. Unless there is some other application resident that doesn't behave properly this shouldn't cause a problem. The BIOS will normally ignore any function request it doesn't recognize. The likelihood of some other resident program using function request FAH is pretty low. INT 1C - TIMER TICK Check if FASTBUFF is on: The first thing for this interrupt handler is to make sure FASTBUFF is currently active. If it isn't active then we aren't supposed to be doing anything here. Decrement Blanking Counter: If the program is active then we need to decrement the counter that lets us know when the screen is to be blanked. Video Blanking Check: When the counter reaches zero we still have to make sure that the video blanking option is enabled. If the screen is supposed to be blanked then we call the routine that does this and clear the bit that indicates the screen is active. Update BIOS Buffer: As mentioned earlier we aren't using the keyboard i/o interrupt to return characters to the system. We chose this method to improve compatibility with other programs. The updateBIOS procedure will be covered in the next section, but for now we should note the check with the oldint9mask. This check is done to make sure we aren't currently making a call to the old interrupt 9 handler. If we were to try to add characters while BIOS is trying to take them out we will occasionally lose a character or two. We set our own flag for this because the interrupt flag will be reset from within the old int 9 handler if we try to use the CLI instruction. Repeating Keys: If the repeat bit is still set from the interrupt 9 call above then we need to repeat the character stored as the lastchar. This procedure will be described below. UPDATEBIOS This method is used to increase compatibility with other programs that may do low-level keyboard i/o. Using this method we are always transferring characters into the BIOS buffer and letting the system to the retrieval for us. This also allows other programs to access the BIOS buffer directly in order to get input. Check FASTBUFF Buffer: Of course the first step in copying characters from our buffer to the BIOS buffer is to make sure we have something to insert. Transfer to BIOS: If there are characters to copy then we move as many as we can into the BIOS buffer. We must, however, keep in mind that the old BIOS keystroke handler expects to put input characters into its buffer. For this reason we must keep an extra space open for its use when we do the update, otherwise the BIOS routine will just beep at us when we call it. Minimum Buffer Size: Now that you know how this works I can explain why the minimum buffer size is set at 25. In order to avoid a lot of special cases we need to make the minimum at least 15 (14 from the BIOS and 1 in our buffer). However, since we need to occasionally expand our buffer before the BIOS update this is not a good idea, FASTBUFF would then beep if only two characters were received in quick succession. The minimum of 25 allows 14 characters of BIOS storage and 16 in ours. It is nearly impossible to type characters fast enough to fill our buffer before we get a chance to transfer some of them to the BIOS buffer. REPEATING KEYS Set Repeat Rate: The first thing that must be done after we deciding to repeat a key is to reset the repeat count to 1. This allows us to check for a repeat on the next tick again. Back in the character input routines we set the repeat count to the starting delay, which defaults to 5 clicks. Anti-Skid Check: FASTBUFF uses a very simple check to make sure it is not going too fast for the application being used. It just checks the BIOS buffer, and if its empty then we repeat the character, if not we can just wait till the next click and check again. Since we just checked to make sure the buffer was empty, and the minimum buffer size is 25 we know there won't be any problems with filling the buffer either. This allows us to repeat the character without bothering to check if the buffer overflows. Repeating the Key: Next we retrieve the character to be repeated and put 1 (slow repeat) or 2 (fast) copies of it into the BIOS buffer. Note that we must insert more than one character per click to achieve repeat rates faster than 18 characters per second. INITIALIZATION As mentioned above, all I am going to cover here is the check to see if FASTBUFF is already installed. The method was described above anyway, but I'll mention it again just for the heck of it. Since we don't know where in memory FASTBUFF will be installed we need some way other than just looking for a certain string we may have placed in the code. One approach using this method would be to use the DOS call to get the interrupt address for one of the vectors FASTBUFF hooks and then look for such a search string assuming that was the code segment for a previously installed FASTBUFF. The problem with this is that there may be another application installed later that that hooks that vector also. Instead we will allow our interrupt 10 handler an extra function. When we send an function FAH request, FASTBUFF will send back 00FAH in the AX register. If we don't get this code we should be able to assume that FASTBUFF is not already present on the system. Another note on the initialization process is that we don't enable FASTBUFF until well after we have initialized its variables and hooked all the required vectors. This is done to prevent someone from typing ahead during the FASTBUFF initialization and only having part of the required routines to handle the input. Finally we print the initialization message well before hooking any vectors or enabling FASTBUFF. This is because we are using a DOS call to write out output to the screen and the user can hit CTRL-BREAK during this message and halt the program. If this were done after the vectors are hooked and before FASTBUFF terminates and remains resident the system will hang as soon as the next program is run, since the interrupt handlers will be overwritten at that time. BYE Well I hope someone finds this program useful. Sorry I get write such long documentation, but I get started and then hate to leave anything out. If you find any bugs, or have any additional information you think I'll find useful please let me know: David Steiner [D.STEINER] on GEnie 2035 J Apt.6 Lincoln, NE 68510